Version in base suite: 0.101.4+dfsg-0+deb10u1 Base version: clamav_0.101.4+dfsg-0+deb10u1 Target version: clamav_0.102.1+dfsg-0+deb10u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/c/clamav/clamav_0.101.4+dfsg-0+deb10u1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/c/clamav/clamav_0.102.1+dfsg-0+deb10u1.dsc /srv/release.debian.org/tmp/vVAf8ne2pP/clamav-0.102.1+dfsg/docs/UserManual/images/demon.png |binary clamav-0.102.1+dfsg/Makefile.am | 18 clamav-0.102.1+dfsg/Makefile.in | 176 clamav-0.102.1+dfsg/NEWS.md | 205 clamav-0.102.1+dfsg/README.md | 35 clamav-0.102.1+dfsg/aclocal.m4 | 330 clamav-0.102.1+dfsg/clamav-config.h.in | 39 clamav-0.102.1+dfsg/clamav-milter/Makefile.in | 52 clamav-0.102.1+dfsg/clamav-milter/clamav-milter.c | 582 clamav-0.102.1+dfsg/clamav-milter/clamfi.c | 1017 - clamav-0.102.1+dfsg/clamav-milter/clamfi.h | 1 clamav-0.102.1+dfsg/clamav-milter/connpool.c | 284 clamav-0.102.1+dfsg/clamav-milter/netcode.c | 625 clamav-0.102.1+dfsg/clamav-milter/whitelist.c | 287 clamav-0.102.1+dfsg/clamav-types.h.in | 4 clamav-0.102.1+dfsg/clamav-version.h.in | 68 clamav-0.102.1+dfsg/clambc/Makefile.in | 52 clamav-0.102.1+dfsg/clambc/bcrun.c | 457 clamav-0.102.1+dfsg/clamconf/Makefile.am | 4 clamav-0.102.1+dfsg/clamconf/Makefile.in | 56 clamav-0.102.1+dfsg/clamconf/clamconf.c | 568 clamav-0.102.1+dfsg/clamd/Makefile.am | 17 clamav-0.102.1+dfsg/clamd/Makefile.in | 122 clamav-0.102.1+dfsg/clamd/clamav-daemon.service.in | 1 clamav-0.102.1+dfsg/clamd/clamd.c | 331 clamav-0.102.1+dfsg/clamd/fts.c | 1165 - clamav-0.102.1+dfsg/clamd/localserver.c | 142 clamav-0.102.1+dfsg/clamd/onaccess_ddd.c | 599 clamav-0.102.1+dfsg/clamd/onaccess_ddd.h | 49 clamav-0.102.1+dfsg/clamd/onaccess_fan.c | 448 clamav-0.102.1+dfsg/clamd/onaccess_fan.h | 27 clamav-0.102.1+dfsg/clamd/onaccess_hash.c | 675 clamav-0.102.1+dfsg/clamd/onaccess_hash.h | 110 clamav-0.102.1+dfsg/clamd/onaccess_others.c | 121 clamav-0.102.1+dfsg/clamd/onaccess_others.h | 36 clamav-0.102.1+dfsg/clamd/onaccess_scth.c | 164 clamav-0.102.1+dfsg/clamd/onaccess_scth.h | 40 clamav-0.102.1+dfsg/clamd/others.c | 570 clamav-0.102.1+dfsg/clamd/others.h | 13 clamav-0.102.1+dfsg/clamd/priv_fts.h | 221 clamav-0.102.1+dfsg/clamd/scanner.c | 706 clamav-0.102.1+dfsg/clamd/scanner.h | 5 clamav-0.102.1+dfsg/clamd/server-th.c | 1966 +- clamav-0.102.1+dfsg/clamd/server.h | 2 clamav-0.102.1+dfsg/clamd/session.c | 869 - clamav-0.102.1+dfsg/clamd/session.h | 12 clamav-0.102.1+dfsg/clamd/tcpserver.c | 54 clamav-0.102.1+dfsg/clamd/thrmgr.c | 1257 - clamav-0.102.1+dfsg/clamd/thrmgr.h | 86 clamav-0.102.1+dfsg/clamdscan/Makefile.in | 52 clamav-0.102.1+dfsg/clamdscan/clamdscan.c | 154 clamav-0.102.1+dfsg/clamdscan/client.c | 218 clamav-0.102.1+dfsg/clamdscan/proto.c | 721 clamav-0.102.1+dfsg/clamdtop/Makefile.in | 52 clamav-0.102.1+dfsg/clamdtop/clamdtop.c | 1769 +- clamav-0.102.1+dfsg/clamonacc/Makefile.am | 71 clamav-0.102.1+dfsg/clamonacc/Makefile.in | 1158 + clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.c | 551 clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.h | 187 clamav-0.102.1+dfsg/clamonacc/clamonacc.c | 401 clamav-0.102.1+dfsg/clamonacc/clamonacc.h | 85 clamav-0.102.1+dfsg/clamonacc/client/client.c | 441 clamav-0.102.1+dfsg/clamonacc/client/client.h | 46 clamav-0.102.1+dfsg/clamonacc/client/communication.c | 220 clamav-0.102.1+dfsg/clamonacc/client/communication.h | 48 clamav-0.102.1+dfsg/clamonacc/client/protocol.c | 400 clamav-0.102.1+dfsg/clamonacc/client/protocol.h | 31 clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.c | 290 clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.h | 31 clamav-0.102.1+dfsg/clamonacc/inotif/hash.c | 800 + clamav-0.102.1+dfsg/clamonacc/inotif/hash.h | 112 clamav-0.102.1+dfsg/clamonacc/inotif/inotif.c | 773 clamav-0.102.1+dfsg/clamonacc/inotif/inotif.h | 52 clamav-0.102.1+dfsg/clamonacc/misc/fts.c | 1165 + clamav-0.102.1+dfsg/clamonacc/misc/priv_fts.h | 220 clamav-0.102.1+dfsg/clamonacc/misc/utils.c | 236 clamav-0.102.1+dfsg/clamonacc/misc/utils.h | 40 clamav-0.102.1+dfsg/clamonacc/scan/queue.c | 304 clamav-0.102.1+dfsg/clamonacc/scan/queue.h | 43 clamav-0.102.1+dfsg/clamonacc/scan/thread.c | 430 clamav-0.102.1+dfsg/clamonacc/scan/thread.h | 78 clamav-0.102.1+dfsg/clamscan/Makefile.in | 52 clamav-0.102.1+dfsg/clamscan/clamscan.c | 162 clamav-0.102.1+dfsg/clamscan/global.h | 14 clamav-0.102.1+dfsg/clamscan/manager.c | 586 clamav-0.102.1+dfsg/clamsubmit/Makefile.am | 28 clamav-0.102.1+dfsg/clamsubmit/Makefile.in | 209 clamav-0.102.1+dfsg/clamsubmit/clamsubmit.c | 214 clamav-0.102.1+dfsg/config/ar-lib | 2 clamav-0.102.1+dfsg/config/compile | 2 clamav-0.102.1+dfsg/config/config.guess | 858 - clamav-0.102.1+dfsg/config/config.sub | 332 clamav-0.102.1+dfsg/config/depcomp | 6 clamav-0.102.1+dfsg/config/install-sh | 369 clamav-0.102.1+dfsg/config/ltmain.sh | 39 clamav-0.102.1+dfsg/config/missing | 2 clamav-0.102.1+dfsg/config/test-driver | 15 clamav-0.102.1+dfsg/config/ylwrap | 6 clamav-0.102.1+dfsg/configure | 2919 +++ clamav-0.102.1+dfsg/configure.ac | 197 clamav-0.102.1+dfsg/database/Makefile.in | 51 clamav-0.102.1+dfsg/debian/.git-dpm | 14 clamav-0.102.1+dfsg/debian/changelog | 13 clamav-0.102.1+dfsg/debian/clamav-daemon.config.in | 8 clamav-0.102.1+dfsg/debian/clamav-daemon.install | 1 clamav-0.102.1+dfsg/debian/clamav-daemon.postinst.in | 15 clamav-0.102.1+dfsg/debian/clamav-daemon.templates | 5 clamav-0.102.1+dfsg/debian/clamav-docs.doc-base | 4 clamav-0.102.1+dfsg/debian/clamav-docs.docs | 2 clamav-0.102.1+dfsg/debian/clamav-freshclam.postinst.in | 1 clamav-0.102.1+dfsg/debian/libclamav9.install | 1 clamav-0.102.1+dfsg/debian/libclamav9.symbols | 421 clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.7.patch | 2 clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.8.patch | 2 clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.9.patch | 2 clamav-0.102.1+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch | 2 clamav-0.102.1+dfsg/debian/patches/add-support-for-system-tomsfastmath.patch | 20 clamav-0.102.1+dfsg/debian/patches/clamd_dont_depend_on_clamav_demon_socket.patch | 6 clamav-0.102.1+dfsg/debian/rules | 2 clamav-0.102.1+dfsg/docs/Makefile.am | 2 clamav-0.102.1+dfsg/docs/Makefile.in | 53 clamav-0.102.1+dfsg/docs/UserManual.md | 26 clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix.md | 261 clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Debian-Ubuntu.md | 313 clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Redhat-CentOS.md | 302 clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-macOS.md | 364 clamav-0.102.1+dfsg/docs/UserManual/Installation-Windows.md | 106 clamav-0.102.1+dfsg/docs/UserManual/Introduction.md | 145 clamav-0.102.1+dfsg/docs/UserManual/OnAccess.md | 115 clamav-0.102.1+dfsg/docs/UserManual/Signatures.md | 412 clamav-0.102.1+dfsg/docs/UserManual/Signatures/AuthenticodeRules.md | 34 clamav-0.102.1+dfsg/docs/UserManual/Signatures/BodySignatureFormat.md | 90 clamav-0.102.1+dfsg/docs/UserManual/Signatures/BytecodeSignatures.md | 11 clamav-0.102.1+dfsg/docs/UserManual/Signatures/ContainerMetadata.md | 44 clamav-0.102.1+dfsg/docs/UserManual/Signatures/DatabaseInfo.md | 15 clamav-0.102.1+dfsg/docs/UserManual/Signatures/DynamicConfig.md | 81 clamav-0.102.1+dfsg/docs/UserManual/Signatures/EncryptedArchives.md | 23 clamav-0.102.1+dfsg/docs/UserManual/Signatures/ExtendedSignatures.md | 37 clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypeMagic.md | 33 clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypes.md | 120 clamav-0.102.1+dfsg/docs/UserManual/Signatures/FunctionalityLevels.md | 30 clamav-0.102.1+dfsg/docs/UserManual/Signatures/HashSignatures.md | 67 clamav-0.102.1+dfsg/docs/UserManual/Signatures/LogicalSignatures.md | 351 clamav-0.102.1+dfsg/docs/UserManual/Signatures/PhishSigs.md | 682 clamav-0.102.1+dfsg/docs/UserManual/Signatures/Whitelists.md | 23 clamav-0.102.1+dfsg/docs/UserManual/Signatures/YaraRules.md | 37 clamav-0.102.1+dfsg/docs/UserManual/Usage.md | 69 clamav-0.102.1+dfsg/docs/UserManual/Usage/Configuration.md | 149 clamav-0.102.1+dfsg/docs/UserManual/Usage/Scanning.md | 131 clamav-0.102.1+dfsg/docs/UserManual/Usage/SignatureManagement.md | 83 clamav-0.102.1+dfsg/docs/UserManual/development.md | 395 clamav-0.102.1+dfsg/docs/UserManual/libclamav.md | 448 clamav-0.102.1+dfsg/docs/html/UserManual.html | 2 clamav-0.102.1+dfsg/docs/html/UserManual/Installation-Unix.html | 194 clamav-0.102.1+dfsg/docs/html/UserManual/Installation-Unix/Steps-Debian-Ubuntu.html | 332 clamav-0.102.1+dfsg/docs/html/UserManual/Installation-Unix/Steps-Redhat-CentOS.html | 334 clamav-0.102.1+dfsg/docs/html/UserManual/Installation-Unix/Steps-macOS.html | 370 clamav-0.102.1+dfsg/docs/html/UserManual/Installation-Windows.html | 101 clamav-0.102.1+dfsg/docs/html/UserManual/Introduction.html | 68 clamav-0.102.1+dfsg/docs/html/UserManual/OnAccess.html | 121 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures.html | 426 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/AuthenticodeRules.html | 6 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/BodySignatureFormat.html | 49 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/ContainerMetadata.html | 8 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/DatabaseInfo.html | 4 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/DynamicConfig.html | 80 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/EncryptedArchives.html | 6 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/ExtendedSignatures.html | 12 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/FileTypeMagic.html | 10 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/FileTypes.html | 377 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/FunctionalityLevels.html | 3 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/HashSignatures.html | 91 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/LogicalSignatures.html | 245 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/PhishSigs.html | 344 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/Whitelists.html | 9 clamav-0.102.1+dfsg/docs/html/UserManual/Signatures/YaraRules.html | 16 clamav-0.102.1+dfsg/docs/html/UserManual/Usage.html | 30 clamav-0.102.1+dfsg/docs/html/UserManual/Usage/Configuration.html | 20 clamav-0.102.1+dfsg/docs/html/UserManual/Usage/Scanning.html | 30 clamav-0.102.1+dfsg/docs/html/UserManual/Usage/SignatureManagement.html | 14 clamav-0.102.1+dfsg/docs/html/UserManual/development.html | 316 clamav-0.102.1+dfsg/docs/html/UserManual/libclamav.html | 308 clamav-0.102.1+dfsg/docs/man/clambc.1.in | 9 clamav-0.102.1+dfsg/docs/man/clamd.conf.5.in | 37 clamav-0.102.1+dfsg/docs/man/freshclam.1.in | 86 clamav-0.102.1+dfsg/docs/man/freshclam.conf.5.in | 135 clamav-0.102.1+dfsg/etc/Makefile.in | 51 clamav-0.102.1+dfsg/etc/clamd.conf.sample | 134 clamav-0.102.1+dfsg/etc/freshclam.conf.sample | 51 clamav-0.102.1+dfsg/examples/ex1.c | 80 clamav-0.102.1+dfsg/examples/fileprop_analysis/embedpe_sample.c | 10 clamav-0.102.1+dfsg/examples/fileprop_analysis/ftype_sample.c | 8 clamav-0.102.1+dfsg/examples/fileprop_analysis/notpdf_sample.c | 6 clamav-0.102.1+dfsg/examples/fileprop_analysis/old/embedpe_sample.c | 10 clamav-0.102.1+dfsg/examples/fileprop_analysis/old/ftype_sample.c | 8 clamav-0.102.1+dfsg/examples/fileprop_analysis/old/notpdf_sample.c | 2 clamav-0.102.1+dfsg/examples/fileprop_analysis/old/onlype_sample.c | 16 clamav-0.102.1+dfsg/examples/fileprop_analysis/old/sandbox.c | 2 clamav-0.102.1+dfsg/examples/fileprop_analysis/onlype_sample.c | 16 clamav-0.102.1+dfsg/examples/fileprop_analysis/sandbox.c | 2 clamav-0.102.1+dfsg/freshclam/Makefile.am | 24 clamav-0.102.1+dfsg/freshclam/Makefile.in | 136 clamav-0.102.1+dfsg/freshclam/clamav-freshclam.service.in | 2 clamav-0.102.1+dfsg/freshclam/dns.c | 180 clamav-0.102.1+dfsg/freshclam/dns.h | 39 clamav-0.102.1+dfsg/freshclam/execute.c | 59 clamav-0.102.1+dfsg/freshclam/execute.h | 6 clamav-0.102.1+dfsg/freshclam/freshclam.c | 2337 ++ clamav-0.102.1+dfsg/freshclam/freshclamcodes.h | 53 clamav-0.102.1+dfsg/freshclam/manager.c | 2977 --- clamav-0.102.1+dfsg/freshclam/manager.h | 33 clamav-0.102.1+dfsg/freshclam/mirman.c | 394 clamav-0.102.1+dfsg/freshclam/mirman.h | 132 clamav-0.102.1+dfsg/freshclam/nonblock.c | 342 clamav-0.102.1+dfsg/freshclam/nonblock.h | 42 clamav-0.102.1+dfsg/freshclam/notify.c | 136 clamav-0.102.1+dfsg/freshclam/notify.h | 4 clamav-0.102.1+dfsg/fuzz/Makefile.am | 87 clamav-0.102.1+dfsg/fuzz/Makefile.in | 138 clamav-0.102.1+dfsg/libclamav/7z/XzDec.c | 1 clamav-0.102.1+dfsg/libclamav/7z_iface.c | 260 clamav-0.102.1+dfsg/libclamav/7z_iface.h | 2 clamav-0.102.1+dfsg/libclamav/Makefile.am | 44 clamav-0.102.1+dfsg/libclamav/Makefile.in | 160 clamav-0.102.1+dfsg/libclamav/adc.c | 85 clamav-0.102.1+dfsg/libclamav/adc.h | 24 clamav-0.102.1+dfsg/libclamav/apm.c | 93 clamav-0.102.1+dfsg/libclamav/apm.h | 62 clamav-0.102.1+dfsg/libclamav/arc4.c | 30 clamav-0.102.1+dfsg/libclamav/asn1.c | 1228 - clamav-0.102.1+dfsg/libclamav/asn1.h | 2 clamav-0.102.1+dfsg/libclamav/aspack.c | 812 - clamav-0.102.1+dfsg/libclamav/aspack.h | 14 clamav-0.102.1+dfsg/libclamav/autoit.c | 1746 +- clamav-0.102.1+dfsg/libclamav/bignum.h | 10 clamav-0.102.1+dfsg/libclamav/bignum_fast.h | 290 clamav-0.102.1+dfsg/libclamav/binhex.c | 386 clamav-0.102.1+dfsg/libclamav/blob.c | 865 - clamav-0.102.1+dfsg/libclamav/blob.h | 76 clamav-0.102.1+dfsg/libclamav/builtin_bytecodes.h | 121 clamav-0.102.1+dfsg/libclamav/bytecode.c | 4337 ++--- clamav-0.102.1+dfsg/libclamav/bytecode.h | 25 clamav-0.102.1+dfsg/libclamav/bytecode_api.c | 721 clamav-0.102.1+dfsg/libclamav/bytecode_api.h | 246 clamav-0.102.1+dfsg/libclamav/bytecode_api_decl.c | 12 clamav-0.102.1+dfsg/libclamav/bytecode_detect.c | 193 clamav-0.102.1+dfsg/libclamav/bytecode_detect.h | 165 clamav-0.102.1+dfsg/libclamav/bytecode_nojit.c | 31 clamav-0.102.1+dfsg/libclamav/bytecode_priv.h | 26 clamav-0.102.1+dfsg/libclamav/bytecode_vm.c | 1228 - clamav-0.102.1+dfsg/libclamav/c++/Makefile.in | 64 clamav-0.102.1+dfsg/libclamav/c++/aclocal.m4 | 67 clamav-0.102.1+dfsg/libclamav/c++/config/compile | 2 clamav-0.102.1+dfsg/libclamav/c++/config/config.guess | 858 - clamav-0.102.1+dfsg/libclamav/c++/config/config.sub | 332 clamav-0.102.1+dfsg/libclamav/c++/config/depcomp | 6 clamav-0.102.1+dfsg/libclamav/c++/config/install-sh | 369 clamav-0.102.1+dfsg/libclamav/c++/config/ltmain.sh | 39 clamav-0.102.1+dfsg/libclamav/c++/config/missing | 2 clamav-0.102.1+dfsg/libclamav/c++/configure | 67 clamav-0.102.1+dfsg/libclamav/c++/m4/libtool.m4 | 28 clamav-0.102.1+dfsg/libclamav/cache.c | 727 clamav-0.102.1+dfsg/libclamav/clamav.h | 166 clamav-0.102.1+dfsg/libclamav/clambc.h | 173 clamav-0.102.1+dfsg/libclamav/conv.c | 16 clamav-0.102.1+dfsg/libclamav/cpio.c | 414 clamav-0.102.1+dfsg/libclamav/crtmgr.c | 340 clamav-0.102.1+dfsg/libclamav/crtmgr.h | 31 clamav-0.102.1+dfsg/libclamav/crypto.c | 129 clamav-0.102.1+dfsg/libclamav/cvd.c | 955 - clamav-0.102.1+dfsg/libclamav/dconf.c | 360 clamav-0.102.1+dfsg/libclamav/dconf.h | 157 clamav-0.102.1+dfsg/libclamav/default.h | 60 clamav-0.102.1+dfsg/libclamav/disasm-common.h | 662 clamav-0.102.1+dfsg/libclamav/disasm.c | 1131 - clamav-0.102.1+dfsg/libclamav/disasm.h | 2 clamav-0.102.1+dfsg/libclamav/disasmpriv.h | 70 clamav-0.102.1+dfsg/libclamav/dlp.c | 561 clamav-0.102.1+dfsg/libclamav/dlp.h | 42 clamav-0.102.1+dfsg/libclamav/dmg.c | 341 clamav-0.102.1+dfsg/libclamav/dmg.h | 88 clamav-0.102.1+dfsg/libclamav/dsig.c | 181 clamav-0.102.1+dfsg/libclamav/egg.c | 2857 +++ clamav-0.102.1+dfsg/libclamav/egg.h | 115 clamav-0.102.1+dfsg/libclamav/elf.c | 794 - clamav-0.102.1+dfsg/libclamav/elf.h | 8 clamav-0.102.1+dfsg/libclamav/encoding_aliases.h | 131 clamav-0.102.1+dfsg/libclamav/entconv.c | 1205 - clamav-0.102.1+dfsg/libclamav/entconv.h | 19 clamav-0.102.1+dfsg/libclamav/entitylist.h | 4099 ++--- clamav-0.102.1+dfsg/libclamav/events.c | 339 clamav-0.102.1+dfsg/libclamav/events.h | 24 clamav-0.102.1+dfsg/libclamav/execs.c | 81 clamav-0.102.1+dfsg/libclamav/execs.h | 134 clamav-0.102.1+dfsg/libclamav/explode.c | 518 clamav-0.102.1+dfsg/libclamav/explode.h | 66 clamav-0.102.1+dfsg/libclamav/filetypes.c | 498 clamav-0.102.1+dfsg/libclamav/filetypes.h | 14 clamav-0.102.1+dfsg/libclamav/filetypes_int.h | 325 clamav-0.102.1+dfsg/libclamav/filtering.c | 1049 - clamav-0.102.1+dfsg/libclamav/filtering.h | 12 clamav-0.102.1+dfsg/libclamav/fmap.c | 878 - clamav-0.102.1+dfsg/libclamav/fmap.h | 72 clamav-0.102.1+dfsg/libclamav/fpu.c | 8 clamav-0.102.1+dfsg/libclamav/fpu.h | 8 clamav-0.102.1+dfsg/libclamav/fsg.c | 132 clamav-0.102.1+dfsg/libclamav/fsg.h | 5 clamav-0.102.1+dfsg/libclamav/gpt.c | 249 clamav-0.102.1+dfsg/libclamav/gpt.h | 34 clamav-0.102.1+dfsg/libclamav/hashtab.c | 1327 - clamav-0.102.1+dfsg/libclamav/hashtab.h | 137 clamav-0.102.1+dfsg/libclamav/hfsplus.c | 178 clamav-0.102.1+dfsg/libclamav/hfsplus.h | 271 clamav-0.102.1+dfsg/libclamav/hostid.c | 38 clamav-0.102.1+dfsg/libclamav/htmlnorm.c | 3395 ++-- clamav-0.102.1+dfsg/libclamav/htmlnorm.h | 6 clamav-0.102.1+dfsg/libclamav/hwp.c | 945 - clamav-0.102.1+dfsg/libclamav/hwp.h | 22 clamav-0.102.1+dfsg/libclamav/iana_tld.h | 1393 - clamav-0.102.1+dfsg/libclamav/iowrap.c | 9 clamav-0.102.1+dfsg/libclamav/is_tar.c | 82 clamav-0.102.1+dfsg/libclamav/is_tar.h | 44 clamav-0.102.1+dfsg/libclamav/ishield.c | 982 - clamav-0.102.1+dfsg/libclamav/iso9660.c | 385 clamav-0.102.1+dfsg/libclamav/jpeg.c | 350 clamav-0.102.1+dfsg/libclamav/json_api.c | 102 clamav-0.102.1+dfsg/libclamav/json_api.h | 94 clamav-0.102.1+dfsg/libclamav/jsparse/js-norm.c | 2515 +-- clamav-0.102.1+dfsg/libclamav/jsparse/js-norm.h | 2 clamav-0.102.1+dfsg/libclamav/jsparse/lexglobal.h | 188 clamav-0.102.1+dfsg/libclamav/jsparse/textbuf.h | 49 clamav-0.102.1+dfsg/libclamav/libclamav.map | 7 clamav-0.102.1+dfsg/libclamav/libmspack.c | 873 - clamav-0.102.1+dfsg/libclamav/line.c | 46 clamav-0.102.1+dfsg/libclamav/line.h | 12 clamav-0.102.1+dfsg/libclamav/lzma_iface.c | 114 clamav-0.102.1+dfsg/libclamav/lzma_iface.h | 1 clamav-0.102.1+dfsg/libclamav/lzw/lzwdec.c | 202 clamav-0.102.1+dfsg/libclamav/lzw/lzwdec.h | 24 clamav-0.102.1+dfsg/libclamav/macho.c | 769 clamav-0.102.1+dfsg/libclamav/macho.h | 1 clamav-0.102.1+dfsg/libclamav/matcher-ac.c | 1971 +- clamav-0.102.1+dfsg/libclamav/matcher-ac.h | 38 clamav-0.102.1+dfsg/libclamav/matcher-bm.c | 609 clamav-0.102.1+dfsg/libclamav/matcher-bm.h | 10 clamav-0.102.1+dfsg/libclamav/matcher-byte-comp.c | 405 clamav-0.102.1+dfsg/libclamav/matcher-byte-comp.h | 21 clamav-0.102.1+dfsg/libclamav/matcher-hash.c | 369 clamav-0.102.1+dfsg/libclamav/matcher-pcre.c | 294 clamav-0.102.1+dfsg/libclamav/matcher-pcre.h | 14 clamav-0.102.1+dfsg/libclamav/matcher.c | 1176 - clamav-0.102.1+dfsg/libclamav/matcher.h | 101 clamav-0.102.1+dfsg/libclamav/mbox.c | 5960 ++++--- clamav-0.102.1+dfsg/libclamav/mbox.h | 29 clamav-0.102.1+dfsg/libclamav/mbr.c | 205 clamav-0.102.1+dfsg/libclamav/mbr.h | 14 clamav-0.102.1+dfsg/libclamav/message.c | 3499 ++-- clamav-0.102.1+dfsg/libclamav/message.h | 114 clamav-0.102.1+dfsg/libclamav/mew.c | 1549 - clamav-0.102.1+dfsg/libclamav/mew.h | 4 clamav-0.102.1+dfsg/libclamav/mpool.c | 766 clamav-0.102.1+dfsg/libclamav/mpool.h | 50 clamav-0.102.1+dfsg/libclamav/msdoc.c | 753 clamav-0.102.1+dfsg/libclamav/msdoc.h | 455 clamav-0.102.1+dfsg/libclamav/msexpand.c | 176 clamav-0.102.1+dfsg/libclamav/msxml.c | 150 clamav-0.102.1+dfsg/libclamav/msxml.h | 4 clamav-0.102.1+dfsg/libclamav/msxml_parser.c | 692 clamav-0.102.1+dfsg/libclamav/msxml_parser.h | 41 clamav-0.102.1+dfsg/libclamav/nsis/nulsft.c | 891 - clamav-0.102.1+dfsg/libclamav/ole2_extract.c | 681 clamav-0.102.1+dfsg/libclamav/ooxml.c | 257 clamav-0.102.1+dfsg/libclamav/openioc.c | 143 clamav-0.102.1+dfsg/libclamav/openioc.h | 6 clamav-0.102.1+dfsg/libclamav/others.c | 1603 +- clamav-0.102.1+dfsg/libclamav/others.h | 372 clamav-0.102.1+dfsg/libclamav/others_common.c | 565 clamav-0.102.1+dfsg/libclamav/packlibs.c | 540 clamav-0.102.1+dfsg/libclamav/pdf.c | 1161 - clamav-0.102.1+dfsg/libclamav/pdf.h | 101 clamav-0.102.1+dfsg/libclamav/pdfdecode.c | 461 clamav-0.102.1+dfsg/libclamav/pdfng.c | 273 clamav-0.102.1+dfsg/libclamav/pe.c | 7798 ++++------ clamav-0.102.1+dfsg/libclamav/pe.h | 207 clamav-0.102.1+dfsg/libclamav/pe_icons.c | 1947 +- clamav-0.102.1+dfsg/libclamav/pe_icons.h | 6 clamav-0.102.1+dfsg/libclamav/pe_structs.h | 159 clamav-0.102.1+dfsg/libclamav/perflogging.c | 134 clamav-0.102.1+dfsg/libclamav/perflogging.h | 48 clamav-0.102.1+dfsg/libclamav/petite.c | 828 - clamav-0.102.1+dfsg/libclamav/phish_domaincheck_db.c | 36 clamav-0.102.1+dfsg/libclamav/phish_domaincheck_db.h | 4 clamav-0.102.1+dfsg/libclamav/phish_whitelist.c | 40 clamav-0.102.1+dfsg/libclamav/phish_whitelist.h | 6 clamav-0.102.1+dfsg/libclamav/phishcheck.c | 2218 +- clamav-0.102.1+dfsg/libclamav/phishcheck.h | 69 clamav-0.102.1+dfsg/libclamav/png.c | 2538 +-- clamav-0.102.1+dfsg/libclamav/prtn_intxn.c | 20 clamav-0.102.1+dfsg/libclamav/qsort.c | 387 clamav-0.102.1+dfsg/libclamav/readdb.c | 5451 +++--- clamav-0.102.1+dfsg/libclamav/readdb.h | 176 clamav-0.102.1+dfsg/libclamav/rebuildpe.c | 237 clamav-0.102.1+dfsg/libclamav/regex/regcomp.c | 2 clamav-0.102.1+dfsg/libclamav/regex_list.c | 1130 - clamav-0.102.1+dfsg/libclamav/regex_list.h | 46 clamav-0.102.1+dfsg/libclamav/regex_pcre.c | 250 clamav-0.102.1+dfsg/libclamav/regex_pcre.h | 22 clamav-0.102.1+dfsg/libclamav/regex_suffix.c | 743 clamav-0.102.1+dfsg/libclamav/regex_suffix.h | 10 clamav-0.102.1+dfsg/libclamav/rtf.c | 1182 - clamav-0.102.1+dfsg/libclamav/scanners.c | 3181 ++-- clamav-0.102.1+dfsg/libclamav/scanners.h | 2 clamav-0.102.1+dfsg/libclamav/sf_base64decode.c | 128 clamav-0.102.1+dfsg/libclamav/sf_base64decode.h | 2 clamav-0.102.1+dfsg/libclamav/sis.c | 1404 - clamav-0.102.1+dfsg/libclamav/special.c | 762 clamav-0.102.1+dfsg/libclamav/special.h | 14 clamav-0.102.1+dfsg/libclamav/spin.c | 321 clamav-0.102.1+dfsg/libclamav/stats.c | 55 clamav-0.102.1+dfsg/libclamav/stats_json.c | 76 clamav-0.102.1+dfsg/libclamav/str.c | 1054 - clamav-0.102.1+dfsg/libclamav/str.h | 46 clamav-0.102.1+dfsg/libclamav/strlcat.c | 40 clamav-0.102.1+dfsg/libclamav/swf.c | 301 clamav-0.102.1+dfsg/libclamav/swf.h | 343 clamav-0.102.1+dfsg/libclamav/table.c | 198 clamav-0.102.1+dfsg/libclamav/table.h | 30 clamav-0.102.1+dfsg/libclamav/text.c | 409 clamav-0.102.1+dfsg/libclamav/text.h | 14 clamav-0.102.1+dfsg/libclamav/textdet.c | 242 clamav-0.102.1+dfsg/libclamav/textnorm.c | 175 clamav-0.102.1+dfsg/libclamav/textnorm.h | 12 clamav-0.102.1+dfsg/libclamav/tiff.c | 122 clamav-0.102.1+dfsg/libclamav/tnef.c | 615 clamav-0.102.1+dfsg/libclamav/type_desc.h | 24 clamav-0.102.1+dfsg/libclamav/unarj.c | 1744 +- clamav-0.102.1+dfsg/libclamav/unarj.h | 16 clamav-0.102.1+dfsg/libclamav/uniq.c | 96 clamav-0.102.1+dfsg/libclamav/uniq.h | 1 clamav-0.102.1+dfsg/libclamav/unsp.c | 746 clamav-0.102.1+dfsg/libclamav/unsp.h | 18 clamav-0.102.1+dfsg/libclamav/untar.c | 577 clamav-0.102.1+dfsg/libclamav/untar.h | 6 clamav-0.102.1+dfsg/libclamav/unzip.c | 1907 +- clamav-0.102.1+dfsg/libclamav/unzip.h | 139 clamav-0.102.1+dfsg/libclamav/upack.c | 1264 - clamav-0.102.1+dfsg/libclamav/upx.c | 816 - clamav-0.102.1+dfsg/libclamav/uuencode.c | 150 clamav-0.102.1+dfsg/libclamav/uuencode.h | 4 clamav-0.102.1+dfsg/libclamav/vba_extract.c | 1833 +- clamav-0.102.1+dfsg/libclamav/vba_extract.h | 32 clamav-0.102.1+dfsg/libclamav/version.c | 2 clamav-0.102.1+dfsg/libclamav/wwunpack.c | 452 clamav-0.102.1+dfsg/libclamav/wwunpack.h | 2 clamav-0.102.1+dfsg/libclamav/www.c | 54 clamav-0.102.1+dfsg/libclamav/xar.c | 467 clamav-0.102.1+dfsg/libclamav/xar.h | 6 clamav-0.102.1+dfsg/libclamav/xdp.c | 22 clamav-0.102.1+dfsg/libclamav/xz_iface.c | 39 clamav-0.102.1+dfsg/libclamav/xz_iface.h | 4 clamav-0.102.1+dfsg/libclamav/yara_clam.h | 191 clamav-0.102.1+dfsg/libclamav/yara_compiler.c | 1171 - clamav-0.102.1+dfsg/libclamav/yara_grammar.c | 490 clamav-0.102.1+dfsg/libclamav/yara_grammar.h | 8 clamav-0.102.1+dfsg/libclamav/yara_grammar.y | 6 clamav-0.102.1+dfsg/libclamav/yara_lexer.c | 705 clamav-0.102.1+dfsg/libclamav/yara_lexer.h | 33 clamav-0.102.1+dfsg/libclamav/yara_lexer.l | 2 clamav-0.102.1+dfsg/libclamav/yara_parser.c | 1414 - clamav-0.102.1+dfsg/libclamav/yc.c | 394 clamav-0.102.1+dfsg/libclamav/yc.h | 2 clamav-0.102.1+dfsg/libclamunrar_iface/unrar_iface.cpp | 311 clamav-0.102.1+dfsg/libclamunrar_iface/unrar_iface.h | 8 clamav-0.102.1+dfsg/libfreshclam/Makefile.am | 61 clamav-0.102.1+dfsg/libfreshclam/Makefile.in | 309 clamav-0.102.1+dfsg/libfreshclam/dns.c | 163 clamav-0.102.1+dfsg/libfreshclam/dns.h | 39 clamav-0.102.1+dfsg/libfreshclam/libfreshclam.c | 1031 - clamav-0.102.1+dfsg/libfreshclam/libfreshclam.h | 276 clamav-0.102.1+dfsg/libfreshclam/libfreshclam.map | 33 clamav-0.102.1+dfsg/libfreshclam/libfreshclam_internal.c | 2279 ++ clamav-0.102.1+dfsg/libfreshclam/libfreshclam_internal.h | 78 clamav-0.102.1+dfsg/libltdl/Makefile.in | 55 clamav-0.102.1+dfsg/m4/libtool.m4 | 28 clamav-0.102.1+dfsg/m4/ltdl.m4 | 2 clamav-0.102.1+dfsg/m4/mmap_private.m4 | 9 clamav-0.102.1+dfsg/m4/reorganization/clamonacc.m4 | 24 clamav-0.102.1+dfsg/m4/reorganization/code_checks/fts.m4 | 4 clamav-0.102.1+dfsg/m4/reorganization/code_checks/iconv.m4 | 52 clamav-0.102.1+dfsg/m4/reorganization/code_checks/readdir.m4 | 46 clamav-0.102.1+dfsg/m4/reorganization/libclamav-only.m4 | 10 clamav-0.102.1+dfsg/m4/reorganization/libfreshclam.m4 | 10 clamav-0.102.1+dfsg/m4/reorganization/libs/curl.m4 | 57 clamav-0.102.1+dfsg/m4/reorganization/libs/iconv.m4 | 288 clamav-0.102.1+dfsg/m4/reorganization/libs/iconv_check.m4 | 19 clamav-0.102.1+dfsg/m4/reorganization/libs/json.m4 | 99 clamav-0.102.1+dfsg/m4/reorganization/libs/libz.m4 | 96 clamav-0.102.1+dfsg/m4/reorganization/libs/xml.m4 | 163 clamav-0.102.1+dfsg/m4/reorganization/substitutions.m4 | 6 clamav-0.102.1+dfsg/m4/reorganization/version.m4 | 37 clamav-0.102.1+dfsg/shared/actions.c | 122 clamav-0.102.1+dfsg/shared/actions.h | 20 clamav-0.102.1+dfsg/shared/cdiff.c | 1509 - clamav-0.102.1+dfsg/shared/cert_util.c | 693 clamav-0.102.1+dfsg/shared/cert_util.h | 121 clamav-0.102.1+dfsg/shared/cert_util_internal.h | 93 clamav-0.102.1+dfsg/shared/clamdcom.c | 120 clamav-0.102.1+dfsg/shared/clamdcom.h | 2 clamav-0.102.1+dfsg/shared/fdpassing.h | 2 clamav-0.102.1+dfsg/shared/getopt.c | 435 clamav-0.102.1+dfsg/shared/getopt.h | 16 clamav-0.102.1+dfsg/shared/hostid.c | 61 clamav-0.102.1+dfsg/shared/hostid.h | 41 clamav-0.102.1+dfsg/shared/idmef_logging.c | 98 clamav-0.102.1+dfsg/shared/idmef_logging.h | 1 clamav-0.102.1+dfsg/shared/linux/cert_util_linux.c | 88 clamav-0.102.1+dfsg/shared/mac/cert_util_mac.m | 399 clamav-0.102.1+dfsg/shared/misc.c | 386 clamav-0.102.1+dfsg/shared/misc.h | 28 clamav-0.102.1+dfsg/shared/optparser.c | 1719 +- clamav-0.102.1+dfsg/shared/optparser.h | 31 clamav-0.102.1+dfsg/shared/output.c | 323 clamav-0.102.1+dfsg/shared/output.h | 4 clamav-0.102.1+dfsg/shared/queue.h | 3 clamav-0.102.1+dfsg/shared/tar.c | 115 clamav-0.102.1+dfsg/shared/win/cert_util_win.c | 173 clamav-0.102.1+dfsg/sigtool/Makefile.in | 52 clamav-0.102.1+dfsg/sigtool/sigtool.c | 5104 +++--- clamav-0.102.1+dfsg/sigtool/vba.c | 2131 +- clamav-0.102.1+dfsg/sigtool/vba.h | 2 clamav-0.102.1+dfsg/test/Makefile.in | 51 clamav-0.102.1+dfsg/unit_tests/Makefile.am | 6 clamav-0.102.1+dfsg/unit_tests/Makefile.in | 61 clamav-0.102.1+dfsg/unit_tests/check_bytecode.c | 228 clamav-0.102.1+dfsg/unit_tests/check_clamav.c | 201 clamav-0.102.1+dfsg/unit_tests/check_clamd.c | 579 clamav-0.102.1+dfsg/unit_tests/check_disasm.c | 291 clamav-0.102.1+dfsg/unit_tests/check_fpu_endian.c | 4 clamav-0.102.1+dfsg/unit_tests/check_htmlnorm.c | 223 clamav-0.102.1+dfsg/unit_tests/check_jsnorm.c | 504 clamav-0.102.1+dfsg/unit_tests/check_matchers.c | 420 clamav-0.102.1+dfsg/unit_tests/check_regex.c | 848 - clamav-0.102.1+dfsg/unit_tests/check_str.c | 226 clamav-0.102.1+dfsg/unit_tests/check_uniq.c | 86 clamav-0.102.1+dfsg/unit_tests/checks_common.h | 4 clamav-0.102.1+dfsg/unit_tests/input/api_extract_7.cbc | 26 clamav-0.102.1+dfsg/unit_tests/input/api_files_7.cbc | 124 clamav-0.102.1+dfsg/unit_tests/input/apicalls2_7.cbc | 16 clamav-0.102.1+dfsg/unit_tests/input/apicalls_7.cbc | 16 clamav-0.102.1+dfsg/unit_tests/input/arith_7.cbc | 400 clamav-0.102.1+dfsg/unit_tests/input/debug_7.cbc | 27 clamav-0.102.1+dfsg/unit_tests/input/inf_7.cbc | 4 clamav-0.102.1+dfsg/unit_tests/input/lsig_7.cbc | 6 clamav-0.102.1+dfsg/unit_tests/input/retmagic_7.cbc | 4 clamav-0.102.1+dfsg/unit_tests/input/testadt_7.cbc | 6 555 files changed, 104492 insertions(+), 95119 deletions(-) diff -Nru clamav-0.101.4+dfsg/Makefile.am clamav-0.102.1+dfsg/Makefile.am --- clamav-0.101.4+dfsg/Makefile.am 2019-08-25 09:24:30.000000000 +0000 +++ clamav-0.102.1+dfsg/Makefile.am 2019-11-24 12:55:15.000000000 +0000 @@ -19,28 +19,34 @@ # MA 02110-1301, USA. ACLOCAL_AMFLAGS=-I m4 +if BUILD_LIBCLAMAV_ONLY +SUBDIRS = libclamav -SUBDIRS = libltdl libclamav clamscan clamd clamdscan freshclam sigtool clamconf database docs etc clamav-milter test clamdtop clambc unit_tests +bin_SCRIPTS=clamav-config + +else +SUBDIRS = libltdl libclamav libfreshclam clamscan clamd clamdscan freshclam sigtool clamconf database docs etc clamav-milter test clamdtop clambc unit_tests EXTRA_DIST = examples shared libclamav.pc.in COPYING.bzip2 COPYING.lzma COPYING.unrar COPYING.LGPL COPYING.llvm COPYING.file COPYING.zlib COPYING.getopt COPYING.regex COPYING.YARA COPYING.pcre platform.h.in libclamunrar libclamunrar_iface libclammspack clamdscan/clamdscan.map ChangeLog.md INSTALL.md NEWS.md README.md bin_SCRIPTS=clamav-config -if ENABLE_CLAMSUBMIT -SUBDIRS += clamsubmit +if BUILD_CLAMONACC +SUBDIRS += clamonacc endif -if ENABLE_LIBFRESHCLAM -SUBDIRS += libfreshclam +if ENABLE_CLAMSUBMIT +SUBDIRS += clamsubmit endif if ENABLE_FUZZ SUBDIRS += fuzz endif +endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libclamav.pc -nodist_include_HEADERS = clamav-types.h +nodist_include_HEADERS = clamav-types.h clamav-version.h # don't complain that configuration files and databases are not removed, this is intended distuninstallcheck_listfiles = find . -type f ! -name clamd.conf ! -name freshclam.conf ! -name daily.cvd ! -name main.cvd -print diff -Nru clamav-0.101.4+dfsg/Makefile.in clamav-0.102.1+dfsg/Makefile.in --- clamav-0.101.4+dfsg/Makefile.in 2019-08-25 09:24:30.000000000 +0000 +++ clamav-0.102.1+dfsg/Makefile.in 2019-11-24 12:55:15.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -37,7 +37,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -101,38 +111,10 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@ENABLE_CLAMSUBMIT_TRUE@am__append_1 = clamsubmit -@ENABLE_LIBFRESHCLAM_TRUE@am__append_2 = libfreshclam -@ENABLE_FUZZ_TRUE@am__append_3 = fuzz +@BUILD_CLAMONACC_TRUE@@BUILD_LIBCLAMAV_ONLY_FALSE@am__append_1 = clamonacc +@BUILD_LIBCLAMAV_ONLY_FALSE@@ENABLE_CLAMSUBMIT_TRUE@am__append_2 = clamsubmit +@BUILD_LIBCLAMAV_ONLY_FALSE@@ENABLE_FUZZ_TRUE@am__append_3 = fuzz subdir = . -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/clamav-config.h.in \ - $(top_srcdir)/libclammspack/config.h.in \ - $(srcdir)/clamav-config.in $(srcdir)/libclamav.pc.in \ - $(srcdir)/platform.h.in \ - $(top_srcdir)/docs/man/clamav-milter.8.in \ - $(top_srcdir)/docs/man/clamav-milter.conf.5.in \ - $(top_srcdir)/docs/man/clambc.1.in \ - $(top_srcdir)/docs/man/clamconf.1.in \ - $(top_srcdir)/docs/man/clamd.8.in \ - $(top_srcdir)/docs/man/clamd.conf.5.in \ - $(top_srcdir)/docs/man/clamdscan.1.in \ - $(top_srcdir)/docs/man/clamscan.1.in \ - $(top_srcdir)/docs/man/freshclam.1.in \ - $(top_srcdir)/docs/man/freshclam.conf.5.in \ - $(top_srcdir)/docs/man/sigtool.1.in \ - $(top_srcdir)/docs/man/clamdtop.1.in \ - $(top_srcdir)/docs/man/clamsubmit.1.in \ - $(srcdir)/clamav-types.h.in COPYING config/ar-lib \ - config/compile config/config.guess config/config.rpath \ - config/config.sub config/install-sh config/missing \ - config/ylwrap config/ltmain.sh $(top_srcdir)/config/ar-lib \ - $(top_srcdir)/config/compile $(top_srcdir)/config/config.guess \ - $(top_srcdir)/config/config.rpath \ - $(top_srcdir)/config/config.sub \ - $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ - $(top_srcdir)/config/missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -145,6 +127,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -169,7 +152,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -187,7 +171,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -203,9 +186,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -213,17 +196,19 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = clamav-config.h $(top_builddir)/libclammspack/config.h CONFIG_CLEAN_FILES = clamav-config libclamav.pc platform.h \ - docs/man/clamav-milter.8 docs/man/clamav-milter.conf.5 \ - docs/man/clambc.1 docs/man/clamconf.1 docs/man/clamd.8 \ - docs/man/clamd.conf.5 docs/man/clamdscan.1 docs/man/clamscan.1 \ - docs/man/freshclam.1 docs/man/freshclam.conf.5 \ - docs/man/sigtool.1 docs/man/clamdtop.1 docs/man/clamsubmit.1 \ - clamav-types.h + clamav-types.h clamav-version.h docs/man/clamav-milter.8 \ + docs/man/clamav-milter.conf.5 docs/man/clambc.1 \ + docs/man/clamconf.1 docs/man/clamd.8 docs/man/clamd.conf.5 \ + docs/man/clamdscan.1 docs/man/clamscan.1 docs/man/freshclam.1 \ + docs/man/freshclam.conf.5 docs/man/sigtool.1 \ + docs/man/clamdtop.1 docs/man/clamsubmit.1 CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ @@ -313,9 +298,35 @@ ETAGS = etags CTAGS = ctags CSCOPE = cscope -DIST_SUBDIRS = libltdl libclamav clamscan clamd clamdscan freshclam \ - sigtool clamconf database docs etc clamav-milter test clamdtop \ - clambc unit_tests clamsubmit libfreshclam fuzz +DIST_SUBDIRS = libltdl libclamav libfreshclam clamscan clamd clamdscan \ + freshclam sigtool clamconf database docs etc clamav-milter \ + test clamdtop clambc unit_tests clamonacc clamsubmit fuzz +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/clamav-config.h.in \ + $(srcdir)/clamav-config.in $(srcdir)/clamav-types.h.in \ + $(srcdir)/clamav-version.h.in $(srcdir)/libclamav.pc.in \ + $(srcdir)/platform.h.in $(top_srcdir)/config/ar-lib \ + $(top_srcdir)/config/compile $(top_srcdir)/config/config.guess \ + $(top_srcdir)/config/config.rpath \ + $(top_srcdir)/config/config.sub \ + $(top_srcdir)/config/install-sh $(top_srcdir)/config/ltmain.sh \ + $(top_srcdir)/config/missing \ + $(top_srcdir)/docs/man/clamav-milter.8.in \ + $(top_srcdir)/docs/man/clamav-milter.conf.5.in \ + $(top_srcdir)/docs/man/clambc.1.in \ + $(top_srcdir)/docs/man/clamconf.1.in \ + $(top_srcdir)/docs/man/clamd.8.in \ + $(top_srcdir)/docs/man/clamd.conf.5.in \ + $(top_srcdir)/docs/man/clamdscan.1.in \ + $(top_srcdir)/docs/man/clamdtop.1.in \ + $(top_srcdir)/docs/man/clamscan.1.in \ + $(top_srcdir)/docs/man/clamsubmit.1.in \ + $(top_srcdir)/docs/man/freshclam.1.in \ + $(top_srcdir)/docs/man/freshclam.conf.5.in \ + $(top_srcdir)/docs/man/sigtool.1.in \ + $(top_srcdir)/libclammspack/config.h.in COPYING config/ar-lib \ + config/compile config/config.guess config/config.rpath \ + config/config.sub config/install-sh config/ltmain.sh \ + config/missing config/ylwrap DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) @@ -389,12 +400,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -426,8 +442,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -457,7 +471,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -478,6 +496,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -490,6 +509,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -501,6 +523,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -532,6 +555,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -540,6 +565,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -552,6 +578,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -581,6 +608,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -596,15 +624,22 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = libltdl libclamav clamscan clamd clamdscan freshclam sigtool \ - clamconf database docs etc clamav-milter test clamdtop clambc \ - unit_tests $(am__append_1) $(am__append_2) $(am__append_3) -EXTRA_DIST = examples shared libclamav.pc.in COPYING.bzip2 COPYING.lzma COPYING.unrar COPYING.LGPL COPYING.llvm COPYING.file COPYING.zlib COPYING.getopt COPYING.regex COPYING.YARA COPYING.pcre platform.h.in libclamunrar libclamunrar_iface libclammspack clamdscan/clamdscan.map ChangeLog.md INSTALL.md NEWS.md README.md -bin_SCRIPTS = clamav-config +@BUILD_LIBCLAMAV_ONLY_FALSE@SUBDIRS = libltdl libclamav libfreshclam \ +@BUILD_LIBCLAMAV_ONLY_FALSE@ clamscan clamd clamdscan freshclam \ +@BUILD_LIBCLAMAV_ONLY_FALSE@ sigtool clamconf database docs etc \ +@BUILD_LIBCLAMAV_ONLY_FALSE@ clamav-milter test clamdtop clambc \ +@BUILD_LIBCLAMAV_ONLY_FALSE@ unit_tests $(am__append_1) \ +@BUILD_LIBCLAMAV_ONLY_FALSE@ $(am__append_2) $(am__append_3) +@BUILD_LIBCLAMAV_ONLY_TRUE@SUBDIRS = libclamav $(am__append_1) \ +@BUILD_LIBCLAMAV_ONLY_TRUE@ $(am__append_2) $(am__append_3) +@BUILD_LIBCLAMAV_ONLY_FALSE@bin_SCRIPTS = clamav-config +@BUILD_LIBCLAMAV_ONLY_TRUE@bin_SCRIPTS = clamav-config +@BUILD_LIBCLAMAV_ONLY_FALSE@EXTRA_DIST = examples shared libclamav.pc.in COPYING.bzip2 COPYING.lzma COPYING.unrar COPYING.LGPL COPYING.llvm COPYING.file COPYING.zlib COPYING.getopt COPYING.regex COPYING.YARA COPYING.pcre platform.h.in libclamunrar libclamunrar_iface libclammspack clamdscan/clamdscan.map ChangeLog.md INSTALL.md NEWS.md README.md pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libclamav.pc -nodist_include_HEADERS = clamav-types.h +nodist_include_HEADERS = clamav-types.h clamav-version.h # don't complain that configuration files and databases are not removed, this is intended distuninstallcheck_listfiles = find . -type f ! -name clamd.conf ! -name freshclam.conf ! -name daily.cvd ! -name main.cvd -print @@ -629,7 +664,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -677,6 +711,10 @@ cd $(top_builddir) && $(SHELL) ./config.status $@ platform.h: $(top_builddir)/config.status $(srcdir)/platform.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ +clamav-types.h: $(top_builddir)/config.status $(srcdir)/clamav-types.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +clamav-version.h: $(top_builddir)/config.status $(srcdir)/clamav-version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $@ docs/man/clamav-milter.8: $(top_builddir)/config.status $(top_srcdir)/docs/man/clamav-milter.8.in cd $(top_builddir) && $(SHELL) ./config.status $@ docs/man/clamav-milter.conf.5: $(top_builddir)/config.status $(top_srcdir)/docs/man/clamav-milter.conf.5.in @@ -703,8 +741,6 @@ cd $(top_builddir) && $(SHELL) ./config.status $@ docs/man/clamsubmit.1: $(top_builddir)/config.status $(top_srcdir)/docs/man/clamsubmit.1.in cd $(top_builddir) && $(SHELL) ./config.status $@ -clamav-types.h: $(top_builddir)/config.status $(srcdir)/clamav-types.h.in - cd $(top_builddir) && $(SHELL) ./config.status $@ install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ @@ -981,7 +1017,7 @@ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 @@ -996,17 +1032,17 @@ $(am__post_remove_distdir) dist-tarZ: distdir - @echo WARNING: "Support for shar distribution archives is" \ - "deprecated." >&2 + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir - @echo WARNING: "Support for distribution archives compressed with" \ - "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir @@ -1024,7 +1060,7 @@ distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -1034,23 +1070,23 @@ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) - mkdir $(distdir)/_build $(distdir)/_inst + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ - --srcdir=.. --prefix="$$dc_install_base" \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -1235,6 +1271,8 @@ uninstall-am uninstall-binSCRIPTS \ uninstall-nodist_includeHEADERS uninstall-pkgconfigDATA +.PRECIOUS: Makefile + lcov: ($(MAKE); cd unit_tests; $(MAKE) lcov) quick-check: diff -Nru clamav-0.101.4+dfsg/NEWS.md clamav-0.102.1+dfsg/NEWS.md --- clamav-0.101.4+dfsg/NEWS.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/NEWS.md 2019-11-20 04:42:24.000000000 +0000 @@ -3,24 +3,86 @@ Note: This file refers to the source tarball. Things described here may differ slightly from the binary packages. -## 0.101.4 +## 0.102.1 -ClamAV 0.101.4 is a security patch release that addresses the following issues. +ClamAV 0.102.1 is a security patch release to address the following issues. -- An out of bounds write was possible within ClamAV's NSIS bzip2 library when - attempting decompression in cases where the number of selectors exceeded the - max limit set by the library (CVE-2019-12900). The issue has been resolved - by respecting that limit. - - Thanks to Martin Simmons for reporting the issue [here](https://bugzilla.clamav.net/show_bug.cgi?id=12371) - -- The zip bomb vulnerability mitigated in 0.101.3 has been assigned the - CVE identifier CVE-2019-12625. Unfortunately, a workaround for the zip-bomb - mitigation was immediately identified. To remediate the zip-bomb scantime - issue, a scan time limit has been introduced in 0.101.4. This limit now - resolves ClamAV's vulnerability to CVE-2019-12625. - - The default scan time limit is 2 minutes (120000 milliseconds). +- Fix for the following vulnerability affecting 0.102.0 and 0.101.4 and prior: + - [CVE-2019-15961](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-15961) + A Denial-of-Service (DoS) vulnerability may occur when scanning a specially + crafted email file as a result of excessively long scan times. The issue is + resolved by implementing several maximums in parsing MIME messages and by + optimizing use of memory allocation. + +- Build system fixes to build clamav-milter, to correctly link with libxml2 when + detected, and to correctly detect fanotify for on-access scanning feature + support. + +- Signature load time is significantly reduced by changing to a more efficient + algorithm for loading signature patterns and allocating the AC trie. + Patch courtesy of Alberto Wu. + +- Introduced a new configure option to statically link libjson-c with libclamav. + Static linking with libjson is highly recommended to prevent crashes in + applications that use libclamav alongside another JSON parsing library. + +- Null-dereference fix in email parser when using the `--gen-json` metadata + option. + +- Fixes for Authenticode parsing and certificate signature (.crb database) bugs. + +Special thanks to the following for code contributions and bug reports: + +- Alberto Wu +- Joran Dirk Greef +- Reio Remma + +## 0.102.0 + +ClamAV 0.102.0 includes an assortment improvements and a couple of significant +changes. + +### Major changes + +- The On-Access Scanning feature has been migrated out of `clamd` and into + a brand new utility named `clamonacc`. This utility is similar to + `clamdscan` and `clamav-milter` in that it acts as a client to `clamd`. + This separation from `clamd` means that `clamd` no longer needs to run + with root privileges while scanning potentially malicious files. Instead, + `clamd` may drop privileges to run under an account that does not have + super-user. In addition to improving the security posture of running + `clamd` with On-Access enabled, this update fixed a few outstanding defects: + - On-Access scanning for created and moved files (Extra-Scanning) is fixed. + - VirusEvent for On-Access scans is fixed. + - With `clamonacc`, it is now possible to copy, move, or remove a file if the + scan triggered an alert, just like with `clamdscan`. + For details on how to use the new `clamonacc` On-Access scanner, please + refer to the user manual on [ClamAV.net](http://www.clamav.net/documents/), + and keep an eye out for a new blog post on the topic +- The `freshclam` database update utility has undergone a significant update. + This includes: + - Added support for HTTPS. + - Support for database mirrors hosted on ports other than 80. + - Removal of the mirror management feature (mirrors.dat). + - An all new libfreshclam library API. + +### Notable changes + +- Added support for extracting ESTsoft .egg archives. + This feature is new code developed from scratch using ESTsoft's Egg-archive + specification and without referencing the UnEgg library provided by ESTsoft. + This was necessary because the UnEgg library's license includes restrictions + limiting the commercial use of the UnEgg library. +- The documentation has moved! + - Users should navigate to [ClamAV.net](http://www.clamav.net/documents/) + to view the documentation online. + - The documentation will continue to be provided in HTML format with each + release for offline viewing in the `docs/html` directory. + - The new home for the documentation markdown is in our + [ClamAV FAQ Github repository](https://github.com/Cisco-Talos/clamav-faq) +- To remediate future denial of service conditions caused by excessive scan times, + we introduced a scan time limit. + The default value is 2 minutes (120000 milliseconds). To customize the time limit: @@ -34,27 +96,98 @@ cl_engine_set_num(engine, CL_ENGINE_MAX_SCANTIME, time_limit_milliseconds) ``` - Thanks to David Fifield for reviewing the zip-bomb mitigation in 0.101.3 - and reporting the issue. - -## 0.101.3 - -ClamAV 0.101.3 is a patch release to address a vulnerability to non-recursive -zip bombs. - -A Denial-of-Service (DoS) vulnerability may occur when scanning a zip bomb as a -result of excessively long scan times. The issue is resolved by detecting the -overlapping local file headers which characterize the non-recursive zip bomb -described by David Fifield, -[here](https://www.bamsoftware.com/hacks/zipbomb/). - -Thank you to Hanno Böck for reporting the issue as it relates to ClamAV, -[here](https://bugzilla.clamav.net/show_bug.cgi?id=12356). - -Also included in 0.101.3: +### Other improvements -- Update of bundled the libmspack library from 0.8alpha to 0.10alpha, to - address a buffer overflow vulnerability in libmspack < 0.9.1α. +- Improved Windows executable Authenticode handling, enabling both whitelisting + and blacklisting of files based on code-signing certificates. Additional + improvements to Windows executable (PE file) parsing. + Work courtesy of Andrew Williams. +- Added support for creating bytecode signatures for Mach-O and + ELF executable unpacking. Work courtesy of Jonas Zaddach. +- Re-formatted the entire ClamAV code-base using `clang-format` in conjunction + with our new ClamAV code style specification. See the + [clamav.net blog post](https://blog.clamav.net/2019/02/clamav-adopts-clang-format.html) + for details. +- Integrated ClamAV with Google's [OSS-Fuzz](https://github.com/google/oss-fuzz) + automated fuzzing service with the help of Alex Gaynor. This work has already + proven beneficial, enabling us to identify and fix subtle bugs in both legacy + code and newly developed code. +- The `clamsubmit` tool is now available on Windows. +- The `clamscan` metadata feature (`--gen-json`) is now available on Windows. +- Significantly reduced number of warnings generated when compiling ClamAV with + "-Wall" and "-Wextra" compiler flags and made many subtle improvements to the + consistency of variable types throughout the code. +- Updated the majority of third-party dependencies for ClamAV on Windows. + The source code for each has been removed from the clamav-devel repository. + This means that these dependencies have to be compiled independently of ClamAV. + The added build process complexity is offset by significantly reducing the + difficulty of releasing ClamAV with newer versions of those dependencies. +- During the 0.102 development period, we've also improved our Continuous + Integration (CI) processes. Most recently, we added a CI pipeline definition + to the ClamAV Git repository. This chains together our build and quality + assurance test suites and enables automatic testing of all proposed changes + to ClamAV, with customizable parameters to suit the testing needs of any + given code change. +- Added a new `clamav-version.h` generated header to provide version number + macros in text and numerical format for ClamAV, libclamav, and libfreshclam. +- Improved cross-platform buildability of libxml2. Work courtesy of Eneas U de + Queiroz with supporting ideas pulled from the work of Jim Klimov. + +### Bug fixes + +- Fix to prevent a possible crash when loading LDB type signature databases + and PCRE is not available. Patch courtesy of Tomasz Kojm. +- Fixes to the PDF parser that will improve PDF malware detection efficacy. + Patch courtesy of Clement Lecigne. +- Fix for regular expression phishing signatures (PDB R-type signatures). +- Various other bug fixes. + +### New Requirements + +- Libcurl has become a hard-dependency. Libcurl enables HTTPS support for + `freshclam` and `clamsubmit` as well as communication between `clamonacc` + and `clamd`. +- Libcurl version >= 7.45 is required when building ClamAV from source with + the new On-Access Scanning application (`clamonacc`). Users on Linux operating + systems that package older versions of libcurl (e.g. all versions of CentOS + and Debian versions <= 8) have a number of options: + + 1. Wait for your package maintainer to provide a newer version of libcurl. + 2. Install a newer version of libcurl [from source](https://curl.haxx.se/download.html). + 3. Disable installation of `clamonacc` and On-Access Scanning capabilities + with the `./configure` flag `--disable-clamonacc`. + + Non-Linux users will need to take no actions as they are unaffected by this + new requirement. + +### Acknowledgements + +The ClamAV team thanks the following individuals for their code submissions: + +- Alex Gaynor +- Andrew Williams +- Carlo Landmeter +- Chips +- Clement Lecigne +- Eneas U de Queiroz +- Jim Klimov +- Joe Cooper +- Jonas Zaddach +- Markus Kolb +- Orion Poplawski +- Ørjan Malde +- Paul Arthur +- Rick Wang +- Romain Chollet +- Rosen Penev +- Thomas Jarosch +- Tomasz Kojm +- Tuomo Soini + +Finally, we'd like to thank Joe McGrath for building our quality assurance test suite +and for working diligently to ensure knowledge transfer up until his last day +on the team. Working with you was a pleasure, Joe, and we wish you the best +of luck in your next adventure! ## 0.101.2 diff -Nru clamav-0.101.4+dfsg/README.md clamav-0.102.1+dfsg/README.md --- clamav-0.101.4+dfsg/README.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/README.md 2019-11-20 04:42:24.000000000 +0000 @@ -1,18 +1,23 @@ # ClamAV ClamAV® is an open source antivirus engine for detecting trojans, viruses, - malware & other malicious threats. +malware & other malicious threats. ## Documentation & FAQ -The ClamAV documentation can be found in the [ClamAV User Manual](docs/UserManual.md) with - additional information online in -[our FAQ](https://www.clamav.net/documents). +Official documentation can be found online at +[ClamAV.net](https://www.clamav.net/documents). +Our source code release tarballs also includes a copy of the documentation for +[offline](docs/html/UserManual.html) reading. ## ClamAV Signatures Anyone can learn to read and write ClamAV signatures. Take a look - at the [signature writing documentation](docs/UserManual/Signatures.md) and [phishing signature writing documentation](docs/UserManual/PhishSigs.md) to get started! +at the +[signature writing documentation](https://www.clamav.net/documents/creating-signatures-for-clamav) +and +[phishing signature writing documentation](https://www.clamav.net/documents/phishsigs) +to get started! ## Installation Instructions @@ -24,7 +29,8 @@ the [install instructions](INSTALL.md). For detailed instructions specific to building ClamAV please investigate -our the [Linux/Unix/Mac Install instructions in the User Manual](docs/UserManual/Installation-Unix.md). +our the +[Linux/Unix/Mac Install instructions in the User Manual](https://www.clamav.net/documents/installing-clamav-on-unix-linux-macos-from-source). #### Install from a binary package @@ -48,7 +54,7 @@ directory. For details on how to use either option, head over to the -[Windows Install instructions in the User Manual](docs/UserManual/Installation-Windows.md). +[Windows Install instructions in the User Manual](https://www.clamav.net/documents/installing-clamav-on-windows). ### Upgrading from a previous version @@ -57,23 +63,24 @@ ## ClamAV News -For information about the features in this and prior releases, read [the news](NEWS.md). +For information about the features in this and prior releases, read +[the news](NEWS.md). Catch up on the latest about ClamAV by reading our - [blog](http://blog.clamav.net) and follow us on Twitter @clamav. +[blog](http://blog.clamav.net) and follow us on Twitter @clamav. ## Join the ClamAV Community The best way to get in touch with the ClamAV community is to join our - [our mailing lists](https://www.clamav.net/documents/mailing-lists-faq), and - tune to #clamav on [IRC](irc.freenode.net). +[our mailing lists](https://www.clamav.net/documents/mailing-lists-faq), and +tune to #clamav on [IRC](irc.freenode.net). ## Want to make a contribution? The ClamAV development team welcomes - [code contributions](https://github.com/Cisco-Talos/clamav-devel), - improvements to [our FAQ](https://github.com/Cisco-Talos/clamav-faq), and also - [bug reports](https://bugzilla.clamav.net/). Thanks for joining us! +[code contributions](https://github.com/Cisco-Talos/clamav-devel), +improvements to [our documentation](https://github.com/Cisco-Talos/clamav-faq), and also +[bug reports](https://bugzilla.clamav.net/). Thanks for joining us! ## Credits diff -Nru clamav-0.101.4+dfsg/aclocal.m4 clamav-0.102.1+dfsg/aclocal.m4 --- clamav-0.101.4+dfsg/aclocal.m4 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/aclocal.m4 2019-11-20 04:42:24.000000000 +0000 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.14.1 -*- Autoconf -*- +# generated automatically by aclocal 1.15.1 -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -20,32 +20,63 @@ If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -67,18 +98,19 @@ PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -88,8 +120,10 @@ $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -101,10 +135,11 @@ else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -112,19 +147,17 @@ else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl @@ -178,9 +211,92 @@ AC_MSG_RESULT([yes]) $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) -# Copyright (C) 2002-2013 Free Software Foundation, Inc. +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +# Copyright (C) 2002-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -192,10 +308,10 @@ # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.14' +[am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.14.1], [], +m4_if([$1], [1.15.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -211,12 +327,12 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.14.1])dnl +[AM_AUTOMAKE_VERSION([1.15.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) -# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# Copyright (C) 2011-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -278,7 +394,7 @@ # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -323,15 +439,51 @@ # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_COND_IF -*- Autoconf -*- + +# Copyright (C) 2008-2017 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_COND_IF +# _AM_COND_ELSE +# _AM_COND_ENDIF +# -------------- +# These macros are only used for tracing. +m4_define([_AM_COND_IF]) +m4_define([_AM_COND_ELSE]) +m4_define([_AM_COND_ENDIF]) + +# AM_COND_IF(COND, [IF-TRUE], [IF-FALSE]) +# --------------------------------------- +# If the shell condition COND is true, execute IF-TRUE, otherwise execute +# IF-FALSE. Allow automake to learn about conditional instantiating macros +# (the AC_CONFIG_FOOS). +AC_DEFUN([AM_COND_IF], +[m4_ifndef([_AM_COND_VALUE_$1], + [m4_fatal([$0: no such condition "$1"])])dnl +_AM_COND_IF([$1])dnl +if test -z "$$1_TRUE"; then : + m4_n([$2])[]dnl +m4_ifval([$3], +[_AM_COND_ELSE([$1])dnl +else + $3 +])dnl +_AM_COND_ENDIF([$1])dnl +fi[]dnl ]) # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -362,7 +514,7 @@ Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -553,7 +705,7 @@ # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -629,7 +781,7 @@ # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -719,8 +871,8 @@ # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -793,7 +945,11 @@ END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi -fi]) +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further @@ -822,7 +978,7 @@ done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -833,7 +989,7 @@ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -843,7 +999,7 @@ fi AC_SUBST([install_sh])]) -# Copyright (C) 2003-2013 Free Software Foundation, Inc. +# Copyright (C) 2003-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -862,7 +1018,7 @@ rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) -# Copyright (C) 1998-2013 Free Software Foundation, Inc. +# Copyright (C) 1998-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -882,7 +1038,7 @@ # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -932,7 +1088,7 @@ # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997-2013 Free Software Foundation, Inc. +# Copyright (C) 1997-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -971,7 +1127,7 @@ # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1000,7 +1156,7 @@ AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1047,7 +1203,7 @@ # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1066,7 +1222,7 @@ # Check to make sure that the build environment is sane. -*- Autoconf -*- -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1147,7 +1303,7 @@ rm -f conftest.file ]) -# Copyright (C) 2009-2013 Free Software Foundation, Inc. +# Copyright (C) 2009-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1207,7 +1363,7 @@ _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) -# Copyright (C) 2001-2013 Free Software Foundation, Inc. +# Copyright (C) 2001-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1235,7 +1391,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006-2013 Free Software Foundation, Inc. +# Copyright (C) 2006-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -1254,7 +1410,7 @@ # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004-2013 Free Software Foundation, Inc. +# Copyright (C) 2004-2017 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, diff -Nru clamav-0.101.4+dfsg/clamav-config.h.in clamav-0.102.1+dfsg/clamav-config.h.in --- clamav-0.101.4+dfsg/clamav-config.h.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-config.h.in 2019-11-20 04:42:24.000000000 +0000 @@ -87,9 +87,6 @@ /* "default FD_SETSIZE value" */ #undef DEFAULT_FD_SETSIZE -/* enable libfreshclam */ -#undef ENABLE_LIBFRESHCLAM - /* use fanotify */ #undef FANOTIFY @@ -203,9 +200,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_GRP_H -/* iconv() available */ +/* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV +/* Define to 1 if you have the header file. */ +#undef HAVE_ICONV_H + /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP @@ -224,6 +224,9 @@ /* Define to 1 if you have the 'libjson' library (-ljson). */ #undef HAVE_JSON +/* Define to 1 if you have the `charset' library (-lcharset). */ +#undef HAVE_LIBCHARSET + /* Define to '1' if you have the check.h library */ #undef HAVE_LIBCHECK @@ -254,6 +257,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H +/* Define to 1 if you have the header file. */ +#undef HAVE_LOCALCHARSET_H + +/* Define to 1 if you have the `locale_charset' function. */ +#undef HAVE_LOCALE_CHARSET + /* Define this if a modern libltdl is already installed */ #undef HAVE_LTDL @@ -318,12 +327,6 @@ /* Define to 1 if you have the `readdir' function. */ #undef HAVE_READDIR -/* readdir_r takes 2 arguments */ -#undef HAVE_READDIR_R_2 - -/* readdir_r takes 3 arguments */ -#undef HAVE_READDIR_R_3 - /* Define to 1 if you have the `recvmsg' function. */ #undef HAVE_RECVMSG @@ -465,15 +468,27 @@ /* yara sources are compiled in */ #undef HAVE_YARA +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + /* For internal use only - DO NOT DEFINE */ #undef HAVE__INTERNAL__SHA_COLLECT -/* "Full library version number" */ +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* "Full clamav library version number" */ #undef LIBCLAMAV_FULLVER -/* "Major library version number" */ +/* "Major clamav library version number" */ #undef LIBCLAMAV_MAJORVER +/* "Full freshclam library version number" */ +#undef LIBFRESHCLAM_FULLVER + +/* "Major freshclam library version number" */ +#undef LIBFRESHCLAM_MAJORVER + /* Define if the OS needs help to load dependent libraries for dlopen(). */ #undef LTDL_DLOPEN_DEPLIBS diff -Nru clamav-0.101.4+dfsg/clamav-milter/Makefile.in clamav-0.102.1+dfsg/clamav-milter/Makefile.in --- clamav-0.101.4+dfsg/clamav-milter/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,17 @@ # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -102,8 +112,6 @@ @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@sbin_PROGRAMS = \ @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ clamav-milter$(EXEEXT) subdir = clamav-milter -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -116,6 +124,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -140,7 +149,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -158,7 +168,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -174,9 +183,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -184,6 +193,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -304,6 +314,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -337,12 +348,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -374,8 +390,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -405,7 +419,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -426,6 +444,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -438,6 +457,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -449,6 +471,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -480,6 +503,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -488,6 +513,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -500,6 +526,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -529,6 +556,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -544,6 +572,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@clamav_milter_SOURCES = \ @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/optparser.c \ @BUILD_CLAMD_TRUE@@HAVE_MILTER_TRUE@ $(top_srcdir)/shared/optparser.h \ @@ -583,7 +612,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamav-milter/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamav-milter/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -1024,6 +1052,8 @@ tags tags-am uninstall uninstall-am uninstall-man \ uninstall-man8 uninstall-sbinPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamav-milter/clamav-milter.c clamav-0.102.1+dfsg/clamav-milter/clamav-milter.c --- clamav-0.101.4+dfsg/clamav-milter/clamav-milter.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/clamav-milter.c 2019-11-20 04:42:24.000000000 +0000 @@ -52,14 +52,15 @@ struct smfiDesc descr; struct optstruct *opts; -static void milter_exit(int sig) { +static void milter_exit(int sig) +{ const struct optstruct *opt; logg("*clamav-milter: milter_exit, signal %d\n", sig); #ifndef _WIN32 - if((opt = optget(opts, "MilterSocket"))) { - if(unlink(opt->strarg) == -1) + if ((opt = optget(opts, "MilterSocket"))) { + if (unlink(opt->strarg) == -1) logg("!Can't unlink the socket file %s\n", opt->strarg); else logg("Socket file removed.\n"); @@ -76,7 +77,8 @@ whitelist_free(); } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ char *my_socket, *pt; const struct optstruct *opt; time_t currtime; @@ -104,345 +106,345 @@ cl_initialize_crypto(); memset(&descr, 0, sizeof(struct smfiDesc)); - descr.xxfi_name = "ClamAV"; /* filter name */ - descr.xxfi_version = SMFI_VERSION; /* milter version */ - descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */ - descr.xxfi_connect = clamfi_connect; /* connection info filter */ - descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */ - descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */ - descr.xxfi_header = clamfi_header; /* header filter */ - descr.xxfi_body = clamfi_body; /* body block */ - descr.xxfi_eom = clamfi_eom; /* end of message */ - descr.xxfi_abort = clamfi_abort; /* message aborted */ + descr.xxfi_name = "ClamAV"; /* filter name */ + descr.xxfi_version = SMFI_VERSION; /* milter version */ + descr.xxfi_flags = SMFIF_QUARANTINE; /* flags */ + descr.xxfi_connect = clamfi_connect; /* connection info filter */ + descr.xxfi_envfrom = clamfi_envfrom; /* envelope sender filter */ + descr.xxfi_envrcpt = clamfi_envrcpt; /* envelope recipient filter */ + descr.xxfi_header = clamfi_header; /* header filter */ + descr.xxfi_body = clamfi_body; /* body block */ + descr.xxfi_eom = clamfi_eom; /* end of message */ + descr.xxfi_abort = clamfi_abort; /* message aborted */ opts = optparse(NULL, argc, argv, 1, OPT_MILTER, 0, NULL); if (!opts) { - mprintf("!Can't parse command line options\n"); - return 1; + mprintf("!Can't parse command line options\n"); + return 1; } - if(optget(opts, "help")->enabled) { - printf("\n"); - printf(" Clam AntiVirus: Milter Mail Scanner %s\n", get_version()); - printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n"); - printf(" (C) 2019 Cisco Systems, Inc.\n"); - printf("\n"); - printf(" %s [-c ]\n\n", argv[0]); - printf("\n"); - printf(" --help -h Show this help\n"); - printf(" --version -V Show version\n"); - printf(" --config-file -c Read configuration from file\n"); - printf("\n"); - optfree(opts); - return 0; - } - - if(opts->filename) { - int x; - for(x = 0; opts->filename[x]; x++) - mprintf("^Ignoring option %s\n", opts->filename[x]); - } - - if(optget(opts, "version")->enabled) { - printf("clamav-milter %s\n", get_version()); - optfree(opts); - return 0; + if (optget(opts, "help")->enabled) { + printf("\n"); + printf(" Clam AntiVirus: Milter Mail Scanner %s\n", get_version()); + printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n"); + printf(" (C) 2019 Cisco Systems, Inc.\n"); + printf("\n"); + printf(" %s [-c ]\n\n", argv[0]); + printf("\n"); + printf(" --help -h Show this help\n"); + printf(" --version -V Show version\n"); + printf(" --config-file -c Read configuration from file\n"); + printf("\n"); + optfree(opts); + return 0; + } + + if (opts->filename) { + int x; + for (x = 0; opts->filename[x]; x++) + mprintf("^Ignoring option %s\n", opts->filename[x]); + } + + if (optget(opts, "version")->enabled) { + printf("clamav-milter %s\n", get_version()); + optfree(opts); + return 0; } pt = strdup(optget(opts, "config-file")->strarg); if (pt == NULL) { - printf("Unable to allocate memory for config file\n"); - return 1; + printf("Unable to allocate memory for config file\n"); + return 1; } - if((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) { - printf("%s: cannot parse config file %s\n", argv[0], pt); - free(pt); - return 1; + if ((opts = optparse(pt, 0, NULL, 1, OPT_MILTER, 0, opts)) == NULL) { + printf("%s: cannot parse config file %s\n", argv[0], pt); + free(pt); + return 1; } free(pt); - if((opt = optget(opts, "Chroot"))->enabled) { - if(chdir(opt->strarg) != 0) { - logg("!Cannot change directory to %s\n", opt->strarg); - return 1; - } - if(chroot(opt->strarg) != 0) { - logg("!chroot to %s failed. Are you root?\n", opt->strarg); - return 1; - } + if ((opt = optget(opts, "Chroot"))->enabled) { + if (chdir(opt->strarg) != 0) { + logg("!Cannot change directory to %s\n", opt->strarg); + return 1; + } + if (chroot(opt->strarg) != 0) { + logg("!chroot to %s failed. Are you root?\n", opt->strarg); + return 1; + } } pt = optget(opts, "AddHeader")->strarg; if (strcasecmp(pt, "No")) { - char myname[255]; + char myname[255]; - if (((opt = optget(opts, "ReportHostname"))->enabled && - strncpy(myname, opt->strarg, sizeof(myname))) || - !gethostname(myname, sizeof(myname))) { - - myname[sizeof(myname)-1] = '\0'; - snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", - get_version(), myname); - } else { - snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", - get_version()); - } - xvirushdr[sizeof(xvirushdr)-1] = '\0'; - - descr.xxfi_flags |= SMFIF_ADDHDRS; - - if (strcasecmp(pt, "Add")) { /* Replace or Yes */ - descr.xxfi_flags |= SMFIF_CHGHDRS; - addxvirus = 1; - } else { /* Add */ - addxvirus = 2; - } - } - - if(!(my_socket = optget(opts, "MilterSocket")->strarg)) { - logg("!Please configure the MilterSocket directive\n"); - logg_close(); - optfree(opts); - return 1; - } - - if(smfi_setconn(my_socket) == MI_FAILURE) { - logg("!smfi_setconn failed\n"); - logg_close(); - optfree(opts); - return 1; - } - if(smfi_register(descr) == MI_FAILURE) { - logg("!smfi_register failed\n"); - logg_close(); - optfree(opts); - return 1; + if (((opt = optget(opts, "ReportHostname"))->enabled && + strncpy(myname, opt->strarg, sizeof(myname))) || + !gethostname(myname, sizeof(myname))) { + + myname[sizeof(myname) - 1] = '\0'; + snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s at %s", + get_version(), myname); + } else { + snprintf(xvirushdr, sizeof(xvirushdr), "clamav-milter %s", + get_version()); + } + xvirushdr[sizeof(xvirushdr) - 1] = '\0'; + + descr.xxfi_flags |= SMFIF_ADDHDRS; + + if (strcasecmp(pt, "Add")) { /* Replace or Yes */ + descr.xxfi_flags |= SMFIF_CHGHDRS; + addxvirus = 1; + } else { /* Add */ + addxvirus = 2; + } + } + + if (!(my_socket = optget(opts, "MilterSocket")->strarg)) { + logg("!Please configure the MilterSocket directive\n"); + logg_close(); + optfree(opts); + return 1; + } + + if (smfi_setconn(my_socket) == MI_FAILURE) { + logg("!smfi_setconn failed\n"); + logg_close(); + optfree(opts); + return 1; + } + if (smfi_register(descr) == MI_FAILURE) { + logg("!smfi_register failed\n"); + logg_close(); + optfree(opts); + return 1; } - opt = optget(opts, "FixStaleSocket"); + opt = optget(opts, "FixStaleSocket"); umsk = umask(0777); /* socket is created with 000 to avoid races */ - if(smfi_opensocket(opt->enabled) == MI_FAILURE) { - logg("!Failed to create socket %s\n", my_socket); - logg_close(); - optfree(opts); - return 1; + if (smfi_opensocket(opt->enabled) == MI_FAILURE) { + logg("!Failed to create socket %s\n", my_socket); + logg_close(); + optfree(opts); + return 1; } umask(umsk); /* restore umask */ - if(strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) { - /* set group ownership and perms on the local socket */ - char *sock_name = my_socket; - mode_t sock_mode; - if(!strncmp(my_socket, "unix:", 5)) - sock_name += 5; - if(!strncmp(my_socket, "local:", 6)) - sock_name += 6; - if(*my_socket == ':') - sock_name ++; - - if(optget(opts, "MilterSocketGroup")->enabled) { - char *gname = optget(opts, "MilterSocketGroup")->strarg, *end; - gid_t sock_gid = strtol(gname, &end, 10); - if(*end) { - struct group *pgrp = getgrnam(gname); - if(!pgrp) { - logg("!Unknown group %s\n", gname); - logg_close(); - optfree(opts); - return 1; - } - sock_gid = pgrp->gr_gid; - } - if(chown(sock_name, -1, sock_gid)) { - logg("!Failed to change socket ownership to group %s\n", gname); - logg_close(); - optfree(opts); - return 1; - } - } - - if ((opt = optget(opts, "User"))->enabled) { - struct passwd *user; - if ((user = getpwnam(opt->strarg)) == NULL) { - logg("ERROR: Can't get information about user %s.\n", - opt->strarg); - logg_close(); - optfree(opts); - return 1; - } - - if(chown(sock_name, user->pw_uid, -1)) { - logg("!Failed to change socket ownership to user %s\n", user->pw_name); - optfree(opts); - logg_close(); - return 1; - } - } - - if(optget(opts, "MilterSocketMode")->enabled) { - char *end; - sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8); - if(*end) { - logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg); - logg_close(); - optfree(opts); - return 1; - } - } else - sock_mode = 0777 & ~umsk; - - if(chmod(sock_name, sock_mode & 0666)) { - logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg); - logg_close(); - optfree(opts); - return 1; - } + if (strncmp(my_socket, "inet:", 5) && strncmp(my_socket, "inet6:", 6)) { + /* set group ownership and perms on the local socket */ + char *sock_name = my_socket; + mode_t sock_mode; + if (!strncmp(my_socket, "unix:", 5)) + sock_name += 5; + if (!strncmp(my_socket, "local:", 6)) + sock_name += 6; + if (*my_socket == ':') + sock_name++; + + if (optget(opts, "MilterSocketGroup")->enabled) { + char *gname = optget(opts, "MilterSocketGroup")->strarg, *end; + gid_t sock_gid = strtol(gname, &end, 10); + if (*end) { + struct group *pgrp = getgrnam(gname); + if (!pgrp) { + logg("!Unknown group %s\n", gname); + logg_close(); + optfree(opts); + return 1; + } + sock_gid = pgrp->gr_gid; + } + if (chown(sock_name, -1, sock_gid)) { + logg("!Failed to change socket ownership to group %s\n", gname); + logg_close(); + optfree(opts); + return 1; + } + } + + if ((opt = optget(opts, "User"))->enabled) { + struct passwd *user; + if ((user = getpwnam(opt->strarg)) == NULL) { + logg("ERROR: Can't get information about user %s.\n", + opt->strarg); + logg_close(); + optfree(opts); + return 1; + } + + if (chown(sock_name, user->pw_uid, -1)) { + logg("!Failed to change socket ownership to user %s\n", user->pw_name); + optfree(opts); + logg_close(); + return 1; + } + } + + if (optget(opts, "MilterSocketMode")->enabled) { + char *end; + sock_mode = strtol(optget(opts, "MilterSocketMode")->strarg, &end, 8); + if (*end) { + logg("!Invalid MilterSocketMode %s\n", optget(opts, "MilterSocketMode")->strarg); + logg_close(); + optfree(opts); + return 1; + } + } else + sock_mode = 0777 & ~umsk; + + if (chmod(sock_name, sock_mode & 0666)) { + logg("!Cannot set milter socket permission to %s\n", optget(opts, "MilterSocketMode")->strarg); + logg_close(); + optfree(opts); + return 1; + } } - if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { + if (geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { struct passwd *user = NULL; - if((user = getpwnam(opt->strarg)) == NULL) { - fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); - optfree(opts); - return 1; - } + if ((user = getpwnam(opt->strarg)) == NULL) { + fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); + optfree(opts); + return 1; + } #ifdef HAVE_INITGROUPS - if(initgroups(opt->strarg, user->pw_gid)) { - fprintf(stderr, "ERROR: initgroups() failed.\n"); - optfree(opts); - return 1; - } + if (initgroups(opt->strarg, user->pw_gid)) { + fprintf(stderr, "ERROR: initgroups() failed.\n"); + optfree(opts); + return 1; + } #elif HAVE_SETGROUPS - if(setgroups(1, &user->pw_gid)) { - fprintf(stderr, "ERROR: setgroups() failed.\n"); - optfree(opts); - return 1; - } + if (setgroups(1, &user->pw_gid)) { + fprintf(stderr, "ERROR: setgroups() failed.\n"); + optfree(opts); + return 1; + } #endif - if(setgid(user->pw_gid)) { - fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); - optfree(opts); - return 1; - } - - if(setuid(user->pw_uid)) { - fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); - optfree(opts); - return 1; - } - } - - logg_lock = !optget(opts, "LogFileUnlock")->enabled; - logg_time = optget(opts, "LogTime")->enabled; - logg_size = optget(opts, "LogFileMaxSize")->numarg; + if (setgid(user->pw_gid)) { + fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid); + optfree(opts); + return 1; + } + + if (setuid(user->pw_uid)) { + fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid); + optfree(opts); + return 1; + } + } + + logg_lock = !optget(opts, "LogFileUnlock")->enabled; + logg_time = optget(opts, "LogTime")->enabled; + logg_size = optget(opts, "LogFileMaxSize")->numarg; logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled; if (logg_size) logg_rotate = optget(opts, "LogRotate")->enabled; - if((opt = optget(opts, "LogFile"))->enabled) { - logg_file = opt->strarg; - if(!cli_is_abspath(logg_file)) { - fprintf(stderr, "ERROR: LogFile requires full path.\n"); - logg_close(); - optfree(opts); - return 1; - } + if ((opt = optget(opts, "LogFile"))->enabled) { + logg_file = opt->strarg; + if (!cli_is_abspath(logg_file)) { + fprintf(stderr, "ERROR: LogFile requires full path.\n"); + logg_close(); + optfree(opts); + return 1; + } } else - logg_file = NULL; + logg_file = NULL; #if defined(USE_SYSLOG) && !defined(C_AIX) - if(optget(opts, "LogSyslog")->enabled) { - int fac; + if (optget(opts, "LogSyslog")->enabled) { + int fac; - opt = optget(opts, "LogFacility"); - if((fac = logg_facility(opt->strarg)) == -1) { - logg("!LogFacility: %s: No such facility.\n", opt->strarg); - logg_close(); - optfree(opts); - return 1; - } + opt = optget(opts, "LogFacility"); + if ((fac = logg_facility(opt->strarg)) == -1) { + logg("!LogFacility: %s: No such facility.\n", opt->strarg); + logg_close(); + optfree(opts); + return 1; + } - openlog("clamav-milter", LOG_PID, fac); - logg_syslog = 1; + openlog("clamav-milter", LOG_PID, fac); + logg_syslog = 1; } #endif time(&currtime); - if(logg("#+++ Started at %s", ctime(&currtime))) { - fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); - logg_close(); - optfree(opts); - return 1; - } - if((opt = optget(opts, "TemporaryDirectory"))->enabled) - tempdir = opt->strarg; - - if(localnets_init(opts) || init_actions(opts)) { - logg_close(); - optfree(opts); - return 1; - } - - if((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) { - localnets_free(); - logg_close(); - optfree(opts); - return 1; - } - - if((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) { - localnets_free(); - whitelist_free(); - logg_close(); - optfree(opts); - return 1; + if (logg("#+++ Started at %s", ctime(&currtime))) { + fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); + logg_close(); + optfree(opts); + return 1; + } + if ((opt = optget(opts, "TemporaryDirectory"))->enabled) + tempdir = opt->strarg; + + if (localnets_init(opts) || init_actions(opts)) { + logg_close(); + optfree(opts); + return 1; + } + + if ((opt = optget(opts, "Whitelist"))->enabled && whitelist_init(opt->strarg)) { + localnets_free(); + logg_close(); + optfree(opts); + return 1; + } + + if ((opt = optget(opts, "SkipAuthenticated"))->enabled && smtpauth_init(opt->strarg)) { + localnets_free(); + whitelist_free(); + logg_close(); + optfree(opts); + return 1; } multircpt = optget(opts, "SupportMultipleRecipients")->enabled; - - if(!optget(opts, "Foreground")->enabled) { - if(daemonize() == -1) { - logg("!daemonize() failed\n"); - localnets_free(); - whitelist_free(); - cpool_free(); - logg_close(); - optfree(opts); - return 1; - } - if(chdir("/") == -1) - logg("^Can't change current working directory to root\n"); + + if (!optget(opts, "Foreground")->enabled) { + if (daemonize() == -1) { + logg("!daemonize() failed\n"); + localnets_free(); + whitelist_free(); + cpool_free(); + logg_close(); + optfree(opts); + return 1; + } + if (chdir("/") == -1) + logg("^Can't change current working directory to root\n"); } maxfilesize = optget(opts, "MaxFileSize")->numarg; - if(!maxfilesize) { - logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE); - maxfilesize = CLI_DEFAULT_MAXFILESIZE; + if (!maxfilesize) { + logg("^Invalid MaxFileSize, using default (%d)\n", CLI_DEFAULT_MAXFILESIZE); + maxfilesize = CLI_DEFAULT_MAXFILESIZE; } readtimeout = optget(opts, "ReadTimeout")->numarg; cpool_init(opts); if (!cp) { - logg("!Failed to init the socket pool\n"); - localnets_free(); - whitelist_free(); - logg_close(); - optfree(opts); - return 1; - } - - if((opt = optget(opts, "PidFile"))->enabled) { - FILE *fd; - mode_t old_umask = umask(0002); - - if((fd = fopen(opt->strarg, "w")) == NULL) { - logg("!Can't save PID in file %s\n", opt->strarg); - } else { - if (fprintf(fd, "%u\n", (unsigned int)getpid())<0) { - logg("!Can't save PID in file %s\n", opt->strarg); - } - fclose(fd); - } - umask(old_umask); + logg("!Failed to init the socket pool\n"); + localnets_free(); + whitelist_free(); + logg_close(); + optfree(opts); + return 1; + } + + if ((opt = optget(opts, "PidFile"))->enabled) { + FILE *fd; + mode_t old_umask = umask(0002); + + if ((fd = fopen(opt->strarg, "w")) == NULL) { + logg("!Can't save PID in file %s\n", opt->strarg); + } else { + if (fprintf(fd, "%u\n", (unsigned int)getpid()) < 0) { + logg("!Can't save PID in file %s\n", opt->strarg); + } + fclose(fd); + } + umask(old_umask); } return smfi_main(); diff -Nru clamav-0.101.4+dfsg/clamav-milter/clamfi.c clamav-0.102.1+dfsg/clamav-milter/clamfi.c --- clamav-0.101.4+dfsg/clamav-milter/clamfi.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/clamfi.c 2019-11-20 04:42:24.000000000 +0000 @@ -45,7 +45,7 @@ #include "clamfi.h" #if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) -#define _UNUSED_ __attribute__ ((__unused__)) +#define _UNUSED_ __attribute__((__unused__)) #else #define _UNUSED_ #endif @@ -60,7 +60,7 @@ int addxvirus = 0; /* 0 - don't add | 1 - replace | 2 - add */ char xvirushdr[255]; char *viraction = NULL; -int multircpt = 1; +int multircpt = 1; #define LOGINF_NONE 0 #define LOGINF_BASIC 1 @@ -70,7 +70,7 @@ int loginfected; #define CLAMFIBUFSZ 1424 -static const char *HDR_UNAVAIL = "UNKNOWN"; +static const char *HDR_UNAVAIL = "UNKNOWN"; static pthread_mutex_t virusaction_lock = PTHREAD_MUTEX_INITIALIZER; struct CLAMFI { @@ -93,24 +93,24 @@ char buffer[CLAMFIBUFSZ]; }; - -static void add_x_header(SMFICTX *ctx, char *st, unsigned int scanned, unsigned int status) { - if(addxvirus == 1) { /* Replace/Yes */ - while(scanned) - if(smfi_chgheader(ctx, (char *)"X-Virus-Scanned", scanned--, NULL) != MI_SUCCESS) - logg("^Failed to remove existing X-Virus-Scanned header\n"); - while(status) - if(smfi_chgheader(ctx, (char *)"X-Virus-Status", status--, NULL) != MI_SUCCESS) - logg("^Failed to remove existing X-Virus-Status header\n"); - if(smfi_addheader(ctx, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) - logg("^Failed to add X-Virus-Scanned header\n"); - if(smfi_addheader(ctx, (char *)"X-Virus-Status", st) != MI_SUCCESS) - logg("^Failed to add X-Virus-Status header\n"); +static void add_x_header(SMFICTX *ctx, char *st, unsigned int scanned, unsigned int status) +{ + if (addxvirus == 1) { /* Replace/Yes */ + while (scanned) + if (smfi_chgheader(ctx, (char *)"X-Virus-Scanned", scanned--, NULL) != MI_SUCCESS) + logg("^Failed to remove existing X-Virus-Scanned header\n"); + while (status) + if (smfi_chgheader(ctx, (char *)"X-Virus-Status", status--, NULL) != MI_SUCCESS) + logg("^Failed to remove existing X-Virus-Status header\n"); + if (smfi_addheader(ctx, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) + logg("^Failed to add X-Virus-Scanned header\n"); + if (smfi_addheader(ctx, (char *)"X-Virus-Status", st) != MI_SUCCESS) + logg("^Failed to add X-Virus-Status header\n"); } else { /* Add */ - if(smfi_insheader(ctx, 1, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) - logg("^Failed to insert X-Virus-Scanned header\n"); - if(smfi_insheader(ctx, 1, (char *)"X-Virus-Status", st) != MI_SUCCESS) - logg("^Failed to insert X-Virus-Status header\n"); + if (smfi_insheader(ctx, 1, (char *)"X-Virus-Scanned", xvirushdr) != MI_SUCCESS) + logg("^Failed to insert X-Virus-Scanned header\n"); + if (smfi_insheader(ctx, 1, (char *)"X-Virus-Status", st) != MI_SUCCESS) + logg("^Failed to insert X-Virus-Status header\n"); } } @@ -122,362 +122,364 @@ CF_ANY /* 4 */ }; - -static const char *makesanehdr(char *hdr) { +static const char *makesanehdr(char *hdr) +{ char *ret = hdr; - if(!hdr) return HDR_UNAVAIL; - while(*hdr) { - if(*hdr=='\'' || *hdr=='\t' || *hdr=='\r' || *hdr=='\n' || !isprint(*hdr)) - *hdr = ' '; - hdr++; + if (!hdr) return HDR_UNAVAIL; + while (*hdr) { + if (*hdr == '\'' || *hdr == '\t' || *hdr == '\r' || *hdr == '\n' || !isprint(*hdr)) + *hdr = ' '; + hdr++; } return ret; } -static void nullify(SMFICTX *ctx, struct CLAMFI *cf, enum CFWHAT closewhat) { - if(closewhat & CF_MAIN || ((closewhat & CF_ANY) && cf->main >= 0)) - close(cf->main); - if(closewhat & CF_ALT || ((closewhat & CF_ANY) && cf->alt >= 0)) - close(cf->alt); - if(cf->msg_subj) free(cf->msg_subj); - if(cf->msg_date) free(cf->msg_date); - if(cf->msg_id) free(cf->msg_id); - if(multircpt && cf->nrecipients) { - while(cf->nrecipients) { - cf->nrecipients--; - free(cf->recipients[cf->nrecipients]); - } - free(cf->recipients); +static void nullify(SMFICTX *ctx, struct CLAMFI *cf, enum CFWHAT closewhat) +{ + if (closewhat & CF_MAIN || ((closewhat & CF_ANY) && cf->main >= 0)) + close(cf->main); + if (closewhat & CF_ALT || ((closewhat & CF_ANY) && cf->alt >= 0)) + close(cf->alt); + if (cf->msg_subj) free(cf->msg_subj); + if (cf->msg_date) free(cf->msg_date); + if (cf->msg_id) free(cf->msg_id); + if (multircpt && cf->nrecipients) { + while (cf->nrecipients) { + cf->nrecipients--; + free(cf->recipients[cf->nrecipients]); + } + free(cf->recipients); } smfi_setpriv(ctx, NULL); } - -static sfsistat sendchunk(struct CLAMFI *cf, unsigned char *bodyp, size_t len, SMFICTX *ctx) { - if(cf->totsz >= maxfilesize || len == 0) - return SMFIS_CONTINUE; - - if(!cf->totsz) { - sfsistat ret; - if(nc_connect_rand(&cf->main, &cf->alt, &cf->local)) { - logg("!Failed to initiate streaming/fdpassing\n"); - nullify(ctx, cf, CF_NONE); - return FailAction; - } - cf->totsz = 1; /* do not infloop */ - if((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE) - return ret; - cf->totsz -= 1; +static sfsistat sendchunk(struct CLAMFI *cf, unsigned char *bodyp, size_t len, SMFICTX *ctx) +{ + if (cf->totsz >= maxfilesize || len == 0) + return SMFIS_CONTINUE; + + if (!cf->totsz) { + sfsistat ret; + if (nc_connect_rand(&cf->main, &cf->alt, &cf->local)) { + logg("!Failed to initiate streaming/fdpassing\n"); + nullify(ctx, cf, CF_NONE); + return FailAction; + } + cf->totsz = 1; /* do not infloop */ + if ((ret = sendchunk(cf, (unsigned char *)"From clamav-milter\n", 19, ctx)) != SMFIS_CONTINUE) + return ret; + cf->totsz -= 1; } - if(cf->totsz + len > maxfilesize) - len = maxfilesize - cf->totsz; + if (cf->totsz + len > maxfilesize) + len = maxfilesize - cf->totsz; cf->totsz += len; - if(cf->local) { - while(len) { - int n = write(cf->alt, bodyp, len); - - if (n==-1) { - logg("!Failed to write temporary file\n"); - nullify(ctx, cf, CF_BOTH); - return FailAction; - } - len -= n; - bodyp += n; - } + if (cf->local) { + while (len) { + int n = write(cf->alt, bodyp, len); + + if (n == -1) { + logg("!Failed to write temporary file\n"); + nullify(ctx, cf, CF_BOTH); + return FailAction; + } + len -= n; + bodyp += n; + } } else { - int sendfailed = 0; + int sendfailed = 0; - if(len < CLAMFIBUFSZ - cf->bufsz) { - memcpy(&cf->buffer[cf->bufsz], bodyp, len); - cf->bufsz += len; - } else if(len < CLAMFIBUFSZ) { - memcpy(&cf->buffer[cf->bufsz], bodyp, CLAMFIBUFSZ - cf->bufsz); - cf->sendme = htonl(CLAMFIBUFSZ); - sendfailed = nc_send(cf->main, &cf->sendme, CLAMFIBUFSZ + 4); - len -= (CLAMFIBUFSZ - cf->bufsz); - memcpy(cf->buffer, &bodyp[CLAMFIBUFSZ - cf->bufsz], len); - cf->bufsz = len; - } else { - uint32_t sendmetoo = htonl(len); - cf->sendme = htonl(cf->bufsz); - if((cf->bufsz && nc_send(cf->main, &cf->sendme, cf->bufsz + 4)) || nc_send(cf->main, &sendmetoo, 4) || nc_send(cf->main, bodyp, len)) - sendfailed = 1; - cf->bufsz = 0; - } - if(sendfailed) { - logg("!Streaming failed\n"); - nullify(ctx, cf, CF_NONE); - return FailAction; - } + if (len < CLAMFIBUFSZ - cf->bufsz) { + memcpy(&cf->buffer[cf->bufsz], bodyp, len); + cf->bufsz += len; + } else if (len < CLAMFIBUFSZ) { + memcpy(&cf->buffer[cf->bufsz], bodyp, CLAMFIBUFSZ - cf->bufsz); + cf->sendme = htonl(CLAMFIBUFSZ); + sendfailed = nc_send(cf->main, &cf->sendme, CLAMFIBUFSZ + 4); + len -= (CLAMFIBUFSZ - cf->bufsz); + memcpy(cf->buffer, &bodyp[CLAMFIBUFSZ - cf->bufsz], len); + cf->bufsz = len; + } else { + uint32_t sendmetoo = htonl(len); + cf->sendme = htonl(cf->bufsz); + if ((cf->bufsz && nc_send(cf->main, &cf->sendme, cf->bufsz + 4)) || nc_send(cf->main, &sendmetoo, 4) || nc_send(cf->main, bodyp, len)) + sendfailed = 1; + cf->bufsz = 0; + } + if (sendfailed) { + logg("!Streaming failed\n"); + nullify(ctx, cf, CF_NONE); + return FailAction; + } } return SMFIS_CONTINUE; } - -sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) { +sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) +{ struct CLAMFI *cf; sfsistat ret; - if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) - return SMFIS_CONTINUE; /* whatever */ + if (!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) + return SMFIS_CONTINUE; /* whatever */ - if(!cf->totsz && cf->all_whitelisted) { - logg("*Skipping scan (all destinations whitelisted)\n"); - nullify(ctx, cf, CF_NONE); - free(cf); - return SMFIS_ACCEPT; + if (!cf->totsz && cf->all_whitelisted) { + logg("*Skipping scan (all destinations whitelisted)\n"); + nullify(ctx, cf, CF_NONE); + free(cf); + return SMFIS_ACCEPT; } - if(!headerf) return SMFIS_CONTINUE; /* just in case */ + if (!headerf) return SMFIS_CONTINUE; /* just in case */ - if((loginfected & (LOGINF_FULL | LOGCLN_FULL)) || viraction) { - if(!cf->msg_subj && !strcasecmp(headerf, "Subject")) - cf->msg_subj = strdup(headerv ? headerv : ""); - if(!cf->msg_date && !strcasecmp(headerf, "Date")) - cf->msg_date = strdup(headerv ? headerv : ""); - if(!cf->msg_id && !strcasecmp(headerf, "Message-ID")) - cf->msg_id = strdup(headerv ? headerv : ""); + if ((loginfected & (LOGINF_FULL | LOGCLN_FULL)) || viraction) { + if (!cf->msg_subj && !strcasecmp(headerf, "Subject")) + cf->msg_subj = strdup(headerv ? headerv : ""); + if (!cf->msg_date && !strcasecmp(headerf, "Date")) + cf->msg_date = strdup(headerv ? headerv : ""); + if (!cf->msg_id && !strcasecmp(headerf, "Message-ID")) + cf->msg_id = strdup(headerv ? headerv : ""); } - if(addxvirus==1) { - if(!strcasecmp(headerf, "X-Virus-Scanned")) cf->scanned_count++; - if(!strcasecmp(headerf, "X-Virus-Status")) cf->status_count++; + if (addxvirus == 1) { + if (!strcasecmp(headerf, "X-Virus-Scanned")) cf->scanned_count++; + if (!strcasecmp(headerf, "X-Virus-Status")) cf->status_count++; } - if((ret = sendchunk(cf, (unsigned char *)headerf, strlen(headerf), ctx)) != SMFIS_CONTINUE) { + if ((ret = sendchunk(cf, (unsigned char *)headerf, strlen(headerf), ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } - if((ret = sendchunk(cf, (unsigned char *)": ", 2, ctx)) != SMFIS_CONTINUE) { + if ((ret = sendchunk(cf, (unsigned char *)": ", 2, ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } - if(headerv && (ret = sendchunk(cf, (unsigned char *)headerv, strlen(headerv), ctx)) != SMFIS_CONTINUE) { + if (headerv && (ret = sendchunk(cf, (unsigned char *)headerv, strlen(headerv), ctx)) != SMFIS_CONTINUE) { free(cf); return ret; } ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx); - if(ret != SMFIS_CONTINUE) + if (ret != SMFIS_CONTINUE) free(cf); return ret; } - -sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len) { +sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len) +{ struct CLAMFI *cf; sfsistat ret; - if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) - return SMFIS_CONTINUE; /* whatever */ + if (!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) + return SMFIS_CONTINUE; /* whatever */ - if(!cf->gotbody) { - ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx); - if(ret != SMFIS_CONTINUE) { - free(cf); - return ret; + if (!cf->gotbody) { + ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx); + if (ret != SMFIS_CONTINUE) { + free(cf); + return ret; } - cf->gotbody = 1; + cf->gotbody = 1; } ret = sendchunk(cf, bodyp, len, ctx); - if(ret != SMFIS_CONTINUE) - free(cf); + if (ret != SMFIS_CONTINUE) + free(cf); return ret; } - -sfsistat clamfi_abort(SMFICTX *ctx) { +sfsistat clamfi_abort(SMFICTX *ctx) +{ struct CLAMFI *cf; - if((cf = (struct CLAMFI *)smfi_getpriv(ctx))) { - nullify(ctx, cf, CF_ANY); - free(cf); + if ((cf = (struct CLAMFI *)smfi_getpriv(ctx))) { + nullify(ctx, cf, CF_ANY); + free(cf); } return SMFIS_CONTINUE; } -sfsistat clamfi_eom(SMFICTX *ctx) { +sfsistat clamfi_eom(SMFICTX *ctx) +{ struct CLAMFI *cf; char *reply; int len, ret; unsigned int crcpt; - if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) - return SMFIS_CONTINUE; /* whatever */ + if (!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) + return SMFIS_CONTINUE; /* whatever */ + + if (!cf->totsz) { + /* got no headers and no body */ + logg("*Not scanning an empty message\n"); + ret = CleanAction(ctx); + nullify(ctx, cf, CF_NONE); + free(cf); + return ret; + } + + if (cf->local) { + lseek(cf->alt, 0, SEEK_SET); - if(!cf->totsz) { - /* got no headers and no body */ - logg("*Not scanning an empty message\n"); - ret = CleanAction(ctx); - nullify(ctx, cf, CF_NONE); - free(cf); - return ret; - } - - if(cf->local) { - lseek(cf->alt, 0, SEEK_SET); - - if(nc_sendmsg(cf->main, cf->alt) == -1) { - logg("!FD send failed\n"); - nullify(ctx, cf, CF_ALT); - free(cf); - return FailAction; - } + if (nc_sendmsg(cf->main, cf->alt) == -1) { + logg("!FD send failed\n"); + nullify(ctx, cf, CF_ALT); + free(cf); + return FailAction; + } } else { - uint32_t sendmetoo = 0; - cf->sendme = htonl(cf->bufsz); - if((cf->bufsz && nc_send(cf->main, &cf->sendme, cf->bufsz + 4)) || nc_send(cf->main, &sendmetoo, 4)) { - logg("!Failed to flush STREAM\n"); - nullify(ctx, cf, CF_NONE); - free(cf); - return FailAction; - } + uint32_t sendmetoo = 0; + cf->sendme = htonl(cf->bufsz); + if ((cf->bufsz && nc_send(cf->main, &cf->sendme, cf->bufsz + 4)) || nc_send(cf->main, &sendmetoo, 4)) { + logg("!Failed to flush STREAM\n"); + nullify(ctx, cf, CF_NONE); + free(cf); + return FailAction; + } } reply = nc_recv(cf->main); - if(cf->local) - close(cf->alt); + if (cf->local) + close(cf->alt); cf->alt = -1; - if(!reply) { - logg("!No reply from clamd\n"); - nullify(ctx, cf, CF_NONE); - free(cf); - return FailAction; + if (!reply) { + logg("!No reply from clamd\n"); + nullify(ctx, cf, CF_NONE); + free(cf); + return FailAction; } len = strlen(reply); - if(len>5 && !strcmp(reply + len - 5, ": OK\n")) { - if(addxvirus) add_x_header(ctx, "Clean", cf->scanned_count, cf->status_count); - if(loginfected & LOGCLN_FULL) { - const char *id = smfi_getsymval(ctx, "{i}"); - const char *from = smfi_getsymval(ctx, "{mail_addr}"); - const char *msg_subj = makesanehdr(cf->msg_subj); - const char *msg_date = makesanehdr(cf->msg_date); - const char *msg_id = makesanehdr(cf->msg_id); - if(multircpt && cf->nrecipients) { - for(crcpt = 0; crcpt < cf->nrecipients; crcpt++) - logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, cf->recipients[crcpt], msg_subj, msg_id, msg_date); - } else { - const char *to = smfi_getsymval(ctx, "{rcpt_addr}"); - logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, to ? to : HDR_UNAVAIL, msg_subj, msg_id, msg_date); - } - } else if(loginfected & LOGCLN_BASIC) { - const char *from = smfi_getsymval(ctx, "{mail_addr}"); - if(multircpt && cf->nrecipients) { - for(crcpt = 0; crcpt < cf->nrecipients; crcpt++) - logg("~Clean message from <%s> to <%s>\n", from, cf->recipients[crcpt]); - } else { - const char *to = smfi_getsymval(ctx, "{rcpt_addr}"); - logg("~Clean message from <%s> to <%s>\n", from, to ? to : HDR_UNAVAIL); - } - } - ret = CleanAction(ctx); - } else if (len>7 && !strcmp(reply + len - 7, " FOUND\n")) { - cf->virusname = NULL; - if((loginfected & (LOGINF_BASIC | LOGINF_FULL)) || addxvirus || rejectfmt || viraction) { - char *vir; - - reply[len-7] = '\0'; - vir = strrchr(reply, ' '); - if(vir) { - unsigned int have_multi = (multircpt != 0 && cf->nrecipients); - unsigned int lst_rcpt = (have_multi * (cf->nrecipients - 1)) + 1; - vir++; - - if(rejectfmt) - cf->virusname = vir; - - if(addxvirus) { - char msg[255]; - snprintf(msg, sizeof(msg), "Infected (%s)", vir); - msg[sizeof(msg)-1] = '\0'; - add_x_header(ctx, msg, cf->scanned_count, cf->status_count); - } - - for(crcpt = 0; crcpt < lst_rcpt; crcpt++) { - if(loginfected || viraction) { - const char *from = smfi_getsymval(ctx, "{mail_addr}"); - const char *to = have_multi ? cf->recipients[crcpt] : smfi_getsymval(ctx, "{rcpt_addr}"); - - if(!from) from = HDR_UNAVAIL; - if(!to) to = HDR_UNAVAIL; - if((loginfected & LOGINF_FULL) || viraction) { - const char *id = smfi_getsymval(ctx, "{i}"); - const char *msg_subj = makesanehdr(cf->msg_subj); - const char *msg_date = makesanehdr(cf->msg_date); - const char *msg_id = makesanehdr(cf->msg_id); - - if(!id) id = HDR_UNAVAIL; - - if(loginfected & LOGINF_FULL) - logg("~Message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s' infected by %s\n", id, from, to, msg_subj, msg_id, msg_date, vir); - - if(viraction) { - char er[256]; - char *e_id = strdup(id); - char *e_from = strdup(from); - char *e_to = strdup(to); - char *e_msg_subj = strdup(msg_subj); - char *e_msg_date = strdup(msg_date); - char *e_msg_id = strdup(msg_id); - pid_t pid; - - logg("*VirusEvent: about to execute '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'\n", viraction, vir, e_id, e_from, e_to, e_msg_subj, e_msg_id, e_msg_date); - - pthread_mutex_lock(&virusaction_lock); - pid = fork(); - if(!pid) { - char * args[9]; /* avoid element is not computable at load time warns */ - args[0]= viraction; - args[1] = vir; - args[2] = e_id; - args[3] = e_from; - args[4] = e_to; - args[5] = e_msg_subj; - args[6] = e_msg_id; - args[7] = e_msg_date; - args[8] = NULL; - exit(execvp(viraction, args)); - } else if(pid > 0) { - int wret; - pthread_mutex_unlock(&virusaction_lock); - while((wret = waitpid(pid, &ret, 0)) == -1 && errno == EINTR); - if(wret<0) - logg("!VirusEvent: waitpid() failed: %s\n", cli_strerror(errno, er, sizeof(er))); - else { - if(WIFEXITED(ret)) - logg("*VirusEvent: child exited with code %d\n", WEXITSTATUS(ret)); - else if(WIFSIGNALED(ret)) - logg("*VirusEvent: child killed by signal %d\n", WTERMSIG(ret)); - else - logg("*VirusEvent: child lost\n"); - } - } else { - logg("!VirusEvent: fork failed: %s\n", cli_strerror(errno, er, sizeof(er))); - } - free(e_id); - free(e_from); - free(e_to); - free(e_msg_subj); - free(e_msg_date); - free(e_msg_id); - } - } - if(loginfected & LOGINF_BASIC) - logg("~Message from <%s> to <%s> infected by %s\n", from, to, vir); - } - } - } - } - ret = InfectedAction(ctx); + if (len > 5 && !strcmp(reply + len - 5, ": OK\n")) { + if (addxvirus) add_x_header(ctx, "Clean", cf->scanned_count, cf->status_count); + if (loginfected & LOGCLN_FULL) { + const char *id = smfi_getsymval(ctx, "{i}"); + const char *from = smfi_getsymval(ctx, "{mail_addr}"); + const char *msg_subj = makesanehdr(cf->msg_subj); + const char *msg_date = makesanehdr(cf->msg_date); + const char *msg_id = makesanehdr(cf->msg_id); + if (multircpt && cf->nrecipients) { + for (crcpt = 0; crcpt < cf->nrecipients; crcpt++) + logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, cf->recipients[crcpt], msg_subj, msg_id, msg_date); + } else { + const char *to = smfi_getsymval(ctx, "{rcpt_addr}"); + logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, to ? to : HDR_UNAVAIL, msg_subj, msg_id, msg_date); + } + } else if (loginfected & LOGCLN_BASIC) { + const char *from = smfi_getsymval(ctx, "{mail_addr}"); + if (multircpt && cf->nrecipients) { + for (crcpt = 0; crcpt < cf->nrecipients; crcpt++) + logg("~Clean message from <%s> to <%s>\n", from, cf->recipients[crcpt]); + } else { + const char *to = smfi_getsymval(ctx, "{rcpt_addr}"); + logg("~Clean message from <%s> to <%s>\n", from, to ? to : HDR_UNAVAIL); + } + } + ret = CleanAction(ctx); + } else if (len > 7 && !strcmp(reply + len - 7, " FOUND\n")) { + cf->virusname = NULL; + if ((loginfected & (LOGINF_BASIC | LOGINF_FULL)) || addxvirus || rejectfmt || viraction) { + char *vir; + + reply[len - 7] = '\0'; + vir = strrchr(reply, ' '); + if (vir) { + unsigned int have_multi = (multircpt != 0 && cf->nrecipients); + unsigned int lst_rcpt = (have_multi * (cf->nrecipients - 1)) + 1; + vir++; + + if (rejectfmt) + cf->virusname = vir; + + if (addxvirus) { + char msg[255]; + snprintf(msg, sizeof(msg), "Infected (%s)", vir); + msg[sizeof(msg) - 1] = '\0'; + add_x_header(ctx, msg, cf->scanned_count, cf->status_count); + } + + for (crcpt = 0; crcpt < lst_rcpt; crcpt++) { + if (loginfected || viraction) { + const char *from = smfi_getsymval(ctx, "{mail_addr}"); + const char *to = have_multi ? cf->recipients[crcpt] : smfi_getsymval(ctx, "{rcpt_addr}"); + + if (!from) from = HDR_UNAVAIL; + if (!to) to = HDR_UNAVAIL; + if ((loginfected & LOGINF_FULL) || viraction) { + const char *id = smfi_getsymval(ctx, "{i}"); + const char *msg_subj = makesanehdr(cf->msg_subj); + const char *msg_date = makesanehdr(cf->msg_date); + const char *msg_id = makesanehdr(cf->msg_id); + + if (!id) id = HDR_UNAVAIL; + + if (loginfected & LOGINF_FULL) + logg("~Message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s' infected by %s\n", id, from, to, msg_subj, msg_id, msg_date, vir); + + if (viraction) { + char er[256]; + char *e_id = strdup(id); + char *e_from = strdup(from); + char *e_to = strdup(to); + char *e_msg_subj = strdup(msg_subj); + char *e_msg_date = strdup(msg_date); + char *e_msg_id = strdup(msg_id); + pid_t pid; + + logg("*VirusEvent: about to execute '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'\n", viraction, vir, e_id, e_from, e_to, e_msg_subj, e_msg_id, e_msg_date); + + pthread_mutex_lock(&virusaction_lock); + pid = fork(); + if (!pid) { + char *args[9]; /* avoid element is not computable at load time warns */ + args[0] = viraction; + args[1] = vir; + args[2] = e_id; + args[3] = e_from; + args[4] = e_to; + args[5] = e_msg_subj; + args[6] = e_msg_id; + args[7] = e_msg_date; + args[8] = NULL; + exit(execvp(viraction, args)); + } else if (pid > 0) { + int wret; + pthread_mutex_unlock(&virusaction_lock); + while ((wret = waitpid(pid, &ret, 0)) == -1 && errno == EINTR) continue; + if (wret < 0) + logg("!VirusEvent: waitpid() failed: %s\n", cli_strerror(errno, er, sizeof(er))); + else { + if (WIFEXITED(ret)) + logg("*VirusEvent: child exited with code %d\n", WEXITSTATUS(ret)); + else if (WIFSIGNALED(ret)) + logg("*VirusEvent: child killed by signal %d\n", WTERMSIG(ret)); + else + logg("*VirusEvent: child lost\n"); + } + } else { + logg("!VirusEvent: fork failed: %s\n", cli_strerror(errno, er, sizeof(er))); + } + free(e_id); + free(e_from); + free(e_to); + free(e_msg_subj); + free(e_msg_date); + free(e_msg_id); + } + } + if (loginfected & LOGINF_BASIC) + logg("~Message from <%s> to <%s> infected by %s\n", from, to, vir); + } + } + } + } + ret = InfectedAction(ctx); } else { - logg("!Unknown reply from clamd\n"); - ret = FailAction; + logg("!Unknown reply from clamd\n"); + ret = FailAction; } nullify(ctx, cf, CF_MAIN); @@ -486,273 +488,282 @@ return ret; } - -sfsistat clamfi_connect(_UNUSED_ SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) { - while(1) { - /* Postfix doesn't seem to honor passing a NULL hostaddr and hostname +sfsistat clamfi_connect(_UNUSED_ SMFICTX *ctx, char *hostname, _SOCK_ADDR *hostaddr) +{ + while (1) { + /* Postfix doesn't seem to honor passing a NULL hostaddr and hostname set to "localhost" for non-smtp messages (they still appear as SMTP messages from 127.0.0.1). Here's a small workaround. */ - if(hostaddr) { - if(islocalnet_sock(hostaddr)) { - logg("*Skipping scan for %s (in LocalNet)\n", hostname); - return SMFIS_ACCEPT; - } - break; - } - if(!strcasecmp(hostname, "localhost")) - hostname = NULL; - if(islocalnet_name(hostname)) { - logg("*Skipping scan for %s (in LocalNet)\n", hostname ? hostname : "local"); - return SMFIS_ACCEPT; - } - break; + if (hostaddr) { + if (islocalnet_sock(hostaddr)) { + logg("*Skipping scan for %s (in LocalNet)\n", hostname); + return SMFIS_ACCEPT; + } + break; + } + if (!strcasecmp(hostname, "localhost")) + hostname = NULL; + if (islocalnet_name(hostname)) { + logg("*Skipping scan for %s (in LocalNet)\n", hostname ? hostname : "local"); + return SMFIS_ACCEPT; + } + break; } return SMFIS_CONTINUE; } - -static int parse_action(char *action) { - if(!strcasecmp(action, "Accept")) - return 0; - if(!strcasecmp(action, "Defer")) - return 1; - if(!strcasecmp(action, "Reject")) - return 2; - if(!strcasecmp(action, "Blackhole")) - return 3; - if(!strcasecmp(action, "Quarantine")) - return 4; +static int parse_action(char *action) +{ + if (!strcasecmp(action, "Accept")) + return 0; + if (!strcasecmp(action, "Defer")) + return 1; + if (!strcasecmp(action, "Reject")) + return 2; + if (!strcasecmp(action, "Blackhole")) + return 3; + if (!strcasecmp(action, "Quarantine")) + return 4; logg("!Unknown action %s\n", action); return -1; } - -static sfsistat action_accept(_UNUSED_ SMFICTX *ctx) { +static sfsistat action_accept(_UNUSED_ SMFICTX *ctx) +{ return SMFIS_ACCEPT; } -static sfsistat action_defer(_UNUSED_ SMFICTX *ctx) { +static sfsistat action_defer(_UNUSED_ SMFICTX *ctx) +{ return SMFIS_TEMPFAIL; } -static sfsistat action_reject(_UNUSED_ SMFICTX *ctx) { +static sfsistat action_reject(_UNUSED_ SMFICTX *ctx) +{ return SMFIS_REJECT; } -static sfsistat action_blackhole(_UNUSED_ SMFICTX *ctx) { +static sfsistat action_blackhole(_UNUSED_ SMFICTX *ctx) +{ return SMFIS_DISCARD; } -static sfsistat action_quarantine(SMFICTX *ctx) { - if(smfi_quarantine(ctx, "quarantined by clamav-milter") != MI_SUCCESS) { - logg("^Failed to quarantine message\n"); - return SMFIS_TEMPFAIL; +static sfsistat action_quarantine(SMFICTX *ctx) +{ + if (smfi_quarantine(ctx, "quarantined by clamav-milter") != MI_SUCCESS) { + logg("^Failed to quarantine message\n"); + return SMFIS_TEMPFAIL; } return SMFIS_ACCEPT; } -static sfsistat action_reject_msg(SMFICTX *ctx) { +static sfsistat action_reject_msg(SMFICTX *ctx) +{ struct CLAMFI *cf; char buf[1024]; - if(!rejectfmt || !(cf = (struct CLAMFI *)smfi_getpriv(ctx))) - return SMFIS_REJECT; + if (!rejectfmt || !(cf = (struct CLAMFI *)smfi_getpriv(ctx))) + return SMFIS_REJECT; snprintf(buf, sizeof(buf), rejectfmt, cf->virusname); - buf[sizeof(buf)-1] = '\0'; + buf[sizeof(buf) - 1] = '\0'; smfi_setreply(ctx, "550", "5.7.1", buf); return SMFIS_REJECT; } -int init_actions(struct optstruct *opts) { +int init_actions(struct optstruct *opts) +{ const struct optstruct *opt; - if(!(opt = optget(opts, "LogInfected"))->enabled || !strcasecmp(opt->strarg, "Off")) - loginfected = LOGINF_NONE; - else if(!strcasecmp(opt->strarg, "Basic")) - loginfected = LOGINF_BASIC; - else if(!strcasecmp(opt->strarg, "Full")) - loginfected = LOGINF_FULL; + if (!(opt = optget(opts, "LogInfected"))->enabled || !strcasecmp(opt->strarg, "Off")) + loginfected = LOGINF_NONE; + else if (!strcasecmp(opt->strarg, "Basic")) + loginfected = LOGINF_BASIC; + else if (!strcasecmp(opt->strarg, "Full")) + loginfected = LOGINF_FULL; else { - logg("!Invalid setting %s for option LogInfected\n", opt->strarg); - return 1; + logg("!Invalid setting %s for option LogInfected\n", opt->strarg); + return 1; + } + + if ((opt = optget(opts, "LogClean"))->enabled) { + if (!strcasecmp(opt->strarg, "Basic")) + loginfected |= LOGCLN_BASIC; + else if (!strcasecmp(opt->strarg, "Full")) + loginfected |= LOGCLN_FULL; + else if (strcasecmp(opt->strarg, "Off")) { + logg("!Invalid setting %s for option LogClean\n", opt->strarg); + return 1; + } } - if((opt = optget(opts, "LogClean"))->enabled) { - if(!strcasecmp(opt->strarg, "Basic")) - loginfected |= LOGCLN_BASIC; - else if(!strcasecmp(opt->strarg, "Full")) - loginfected |= LOGCLN_FULL; - else if(strcasecmp(opt->strarg, "Off")) { - logg("!Invalid setting %s for option LogClean\n", opt->strarg); - return 1; - } - } - - if((opt = optget(opts, "VirusAction"))->enabled) - viraction = strdup(opt->strarg); - - if((opt = optget(opts, "OnFail"))->enabled) { - switch(parse_action(opt->strarg)) { - case 0: - FailAction = SMFIS_ACCEPT; - break; - case 1: - FailAction = SMFIS_TEMPFAIL; - break; - case 2: - FailAction = SMFIS_REJECT; - break; - default: - logg("!Invalid action %s for option OnFail\n", opt->strarg); - return 1; - } - } else FailAction = SMFIS_TEMPFAIL; - - if((opt = optget(opts, "OnClean"))->enabled) { - switch(parse_action(opt->strarg)) { - case 0: - CleanAction = action_accept; - break; - case 1: - CleanAction = action_defer; - break; - case 2: - CleanAction = action_reject; - break; - case 3: - CleanAction = action_blackhole; - break; - case 4: - CleanAction = action_quarantine; - break; - default: - logg("!Invalid action %s for option OnClean\n", opt->strarg); - return 1; - } - } else CleanAction = action_accept; - - if((opt = optget(opts, "OnInfected"))->enabled) { - switch(parse_action(opt->strarg)) { - case 0: - InfectedAction = action_accept; - break; - case 1: - InfectedAction = action_defer; - break; - case 3: - InfectedAction = action_blackhole; - break; - case 4: - InfectedAction = action_quarantine; - break; - case 2: - InfectedAction = action_reject_msg; - if((opt = optget(opts, "RejectMsg"))->enabled) { - const char *src = opt->strarg; - char *dst, c; - int gotpctv = 0; - - rejectfmt = dst = malloc(strlen(src) * 4 + 1); - if(!dst) { - logg("!Failed to allocate memory for RejectMsg\n"); - return 1; - } - while ((c = *src++)) { - if(!isprint(c)) { - logg("!RejectMsg contains non printable characters\n"); - free(rejectfmt); - return 1; - } - *dst++ = c; - if(c == '%') { - if(*src == 'v') { - if(gotpctv) { - logg("!%%v may appear at most once in RejectMsg\n"); - free(rejectfmt); - return 1; - } - gotpctv |= 1; - src++; - *dst++ = 's'; - } else { - dst[0] = dst[1] = dst[2] = '%'; - dst += 3; - } - } - } - *dst = '\0'; - } - break; - default: - logg("!Invalid action %s for option OnInfected\n", opt->strarg); - return 1; - } - } else InfectedAction = action_quarantine; + if ((opt = optget(opts, "VirusAction"))->enabled) + viraction = strdup(opt->strarg); + + if ((opt = optget(opts, "OnFail"))->enabled) { + switch (parse_action(opt->strarg)) { + case 0: + FailAction = SMFIS_ACCEPT; + break; + case 1: + FailAction = SMFIS_TEMPFAIL; + break; + case 2: + FailAction = SMFIS_REJECT; + break; + default: + logg("!Invalid action %s for option OnFail\n", opt->strarg); + return 1; + } + } else + FailAction = SMFIS_TEMPFAIL; + + if ((opt = optget(opts, "OnClean"))->enabled) { + switch (parse_action(opt->strarg)) { + case 0: + CleanAction = action_accept; + break; + case 1: + CleanAction = action_defer; + break; + case 2: + CleanAction = action_reject; + break; + case 3: + CleanAction = action_blackhole; + break; + case 4: + CleanAction = action_quarantine; + break; + default: + logg("!Invalid action %s for option OnClean\n", opt->strarg); + return 1; + } + } else + CleanAction = action_accept; + + if ((opt = optget(opts, "OnInfected"))->enabled) { + switch (parse_action(opt->strarg)) { + case 0: + InfectedAction = action_accept; + break; + case 1: + InfectedAction = action_defer; + break; + case 3: + InfectedAction = action_blackhole; + break; + case 4: + InfectedAction = action_quarantine; + break; + case 2: + InfectedAction = action_reject_msg; + if ((opt = optget(opts, "RejectMsg"))->enabled) { + const char *src = opt->strarg; + char *dst, c; + int gotpctv = 0; + + rejectfmt = dst = malloc(strlen(src) * 4 + 1); + if (!dst) { + logg("!Failed to allocate memory for RejectMsg\n"); + return 1; + } + while ((c = *src++)) { + if (!isprint(c)) { + logg("!RejectMsg contains non printable characters\n"); + free(rejectfmt); + return 1; + } + *dst++ = c; + if (c == '%') { + if (*src == 'v') { + if (gotpctv) { + logg("!%%v may appear at most once in RejectMsg\n"); + free(rejectfmt); + return 1; + } + gotpctv |= 1; + src++; + *dst++ = 's'; + } else { + dst[0] = dst[1] = dst[2] = '%'; + dst += 3; + } + } + } + *dst = '\0'; + } + break; + default: + logg("!Invalid action %s for option OnInfected\n", opt->strarg); + return 1; + } + } else + InfectedAction = action_quarantine; return 0; } - -sfsistat clamfi_envfrom(SMFICTX *ctx, char **argv) { +sfsistat clamfi_envfrom(SMFICTX *ctx, char **argv) +{ struct CLAMFI *cf; const char *login = smfi_getsymval(ctx, "{auth_authen}"); - if(login && smtpauthed(login)) { - logg("*Skipping scan for authenticated user %s\n", login); - return SMFIS_ACCEPT; + if (login && smtpauthed(login)) { + logg("*Skipping scan for authenticated user %s\n", login); + return SMFIS_ACCEPT; } - if(whitelisted(argv[0], 1)) { - logg("*Skipping scan for %s (whitelisted from)\n", argv[0]); - return SMFIS_ACCEPT; + if (whitelisted(argv[0], 1)) { + logg("*Skipping scan for %s (whitelisted from)\n", argv[0]); + return SMFIS_ACCEPT; } - if(!(cf = (struct CLAMFI *)malloc(sizeof(*cf)))) { - logg("!Failed to allocate CLAMFI struct\n"); - return FailAction; + if (!(cf = (struct CLAMFI *)malloc(sizeof(*cf)))) { + logg("!Failed to allocate CLAMFI struct\n"); + return FailAction; } cf->totsz = 0; cf->bufsz = 0; - cf->main = cf->alt = -1; + cf->main = cf->alt = -1; cf->all_whitelisted = 1; - cf->gotbody = 0; + cf->gotbody = 0; cf->msg_subj = cf->msg_date = cf->msg_id = NULL; - if(multircpt) { - cf->recipients = NULL; - cf->nrecipients = 0; - } - if(addxvirus==1) { - cf->scanned_count = 0; - cf->status_count = 0; + if (multircpt) { + cf->recipients = NULL; + cf->nrecipients = 0; + } + if (addxvirus == 1) { + cf->scanned_count = 0; + cf->status_count = 0; } smfi_setpriv(ctx, (void *)cf); return SMFIS_CONTINUE; } - -sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv) { +sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv) +{ struct CLAMFI *cf; - if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) - return SMFIS_CONTINUE; /* whatever */ + if (!(cf = (struct CLAMFI *)smfi_getpriv(ctx))) + return SMFIS_CONTINUE; /* whatever */ - if(cf->all_whitelisted) - cf->all_whitelisted &= whitelisted(argv[0], 0); + if (cf->all_whitelisted) + cf->all_whitelisted &= whitelisted(argv[0], 0); - if(multircpt) { - void *new_rcpt = realloc(cf->recipients, (cf->nrecipients + 1) * sizeof(*(cf->recipients))); - unsigned int rcpt_cnt; - if(!new_rcpt) { - logg("!Failed to allocate array for new recipient\n"); - nullify(ctx, cf, CF_ANY); - free(cf); - return FailAction; - } - cf->recipients = new_rcpt; - rcpt_cnt = cf->nrecipients++; - if(!(cf->recipients[rcpt_cnt] = strdup(argv[0]))) { - logg("!Failed to allocate space for new recipient\n"); - nullify(ctx, cf, CF_ANY); - free(cf); - return FailAction; - } + if (multircpt) { + void *new_rcpt = realloc(cf->recipients, (cf->nrecipients + 1) * sizeof(*(cf->recipients))); + unsigned int rcpt_cnt; + if (!new_rcpt) { + logg("!Failed to allocate array for new recipient\n"); + nullify(ctx, cf, CF_ANY); + free(cf); + return FailAction; + } + cf->recipients = new_rcpt; + rcpt_cnt = cf->nrecipients++; + if (!(cf->recipients[rcpt_cnt] = strdup(argv[0]))) { + logg("!Failed to allocate space for new recipient\n"); + nullify(ctx, cf, CF_ANY); + free(cf); + return FailAction; + } } return SMFIS_CONTINUE; diff -Nru clamav-0.101.4+dfsg/clamav-milter/clamfi.h clamav-0.102.1+dfsg/clamav-milter/clamfi.h --- clamav-0.101.4+dfsg/clamav-milter/clamfi.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/clamfi.h 2019-11-20 04:42:24.000000000 +0000 @@ -30,7 +30,6 @@ extern char xvirushdr[255]; extern int multircpt; - sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len); sfsistat clamfi_abort(SMFICTX *ctx); sfsistat clamfi_eom(SMFICTX *ctx); diff -Nru clamav-0.101.4+dfsg/clamav-milter/connpool.c clamav-0.102.1+dfsg/clamav-milter/connpool.c --- clamav-0.101.4+dfsg/clamav-milter/connpool.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/connpool.c 2019-11-20 04:42:24.000000000 +0000 @@ -43,50 +43,62 @@ #include "connpool.h" #include "netcode.h" -#define SETGAI(k, v) {(k)->gai = (void *)(v);} while(0) -#define FREESRV(k) { if((k).gai) freeaddrinfo((k).gai); else if((k).server) free((k).server); } while(0) +#define SETGAI(k, v) \ + { \ + (k)->gai = (void *)(v); \ + } \ + while (0) +#define FREESRV(k) \ + { \ + if ((k).gai) \ + freeaddrinfo((k).gai); \ + else if ((k).server) \ + free((k).server); \ + } \ + while (0) #if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) -#define _UNUSED_ __attribute__ ((__unused__)) +#define _UNUSED_ __attribute__((__unused__)) #else #define _UNUSED_ #endif -struct CPOOL *cp = NULL; +struct CPOOL *cp = NULL; static pthread_cond_t mon_cond = PTHREAD_COND_INITIALIZER; -static int quitting = 1; +static int quitting = 1; static pthread_t probe_th; -static int cpool_addunix(char *path) { +static int cpool_addunix(char *path) +{ struct sockaddr_un *srv; - struct CP_ENTRY *cpe = &cp->pool[cp->entries-1]; + struct CP_ENTRY *cpe = &cp->pool[cp->entries - 1]; - if(!cli_is_abspath(path)) { - logg("!Unix clamd socket must be an absolute path\n"); - return 1; - } - if(!(srv = (struct sockaddr_un *)malloc(sizeof(*srv)))) { - logg("!Out of memory allocating unix socket space\n"); - return 1; + if (!cli_is_abspath(path)) { + logg("!Unix clamd socket must be an absolute path\n"); + return 1; + } + if (!(srv = (struct sockaddr_un *)malloc(sizeof(*srv)))) { + logg("!Out of memory allocating unix socket space\n"); + return 1; } srv->sun_family = AF_UNIX; strncpy(srv->sun_path, path, sizeof(srv->sun_path)); - srv->sun_path[sizeof(srv->sun_path)-1]='\0'; - cpe->type = 0; - cpe->dead = 1; - cpe->local = 1; - cpe->last_poll = 0; - cpe->server = (struct sockaddr *)srv; - cpe->socklen = sizeof(*srv); + srv->sun_path[sizeof(srv->sun_path) - 1] = '\0'; + cpe->type = 0; + cpe->dead = 1; + cpe->local = 1; + cpe->last_poll = 0; + cpe->server = (struct sockaddr *)srv; + cpe->socklen = sizeof(*srv); SETGAI(cpe, NULL); - if(!cp->local_cpe) cp->local_cpe = cpe; + if (!cp->local_cpe) cp->local_cpe = cpe; logg("*Local socket unix:%s added to the pool (slot %d)\n", srv->sun_path, cp->entries); return 0; } - -static int islocal(struct sockaddr *sa, socklen_t addrlen) { +static int islocal(struct sockaddr *sa, socklen_t addrlen) +{ int s = socket(sa->sa_family, SOCK_STREAM, 0); int ret; if (s < 0) return 0; @@ -95,197 +107,197 @@ return ret; } - -static int cpool_addtcp(char *addr, char *port) { +static int cpool_addtcp(char *addr, char *port) +{ struct addrinfo hints, *res, *res2; - struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries-1]; + struct CP_ENTRY *cpe = (struct CP_ENTRY *)&cp->pool[cp->entries - 1]; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - if(getaddrinfo(addr, port ? port : "3310", &hints, &res)) { - logg("^Can't resolve hostname %s\n", addr ? addr : ""); - return 1; + if (getaddrinfo(addr, port ? port : "3310", &hints, &res)) { + logg("^Can't resolve hostname %s\n", addr ? addr : ""); + return 1; } cpe->type = 1; cpe->dead = 1; memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_UNSPEC; - if(!getaddrinfo(addr, NULL, &hints, &res2)) { - cpe->local = islocal(res2->ai_addr, res2->ai_addrlen); - freeaddrinfo(res2); - } else cpe->local = 0; + hints.ai_family = AF_UNSPEC; + if (!getaddrinfo(addr, NULL, &hints, &res2)) { + cpe->local = islocal(res2->ai_addr, res2->ai_addrlen); + freeaddrinfo(res2); + } else + cpe->local = 0; cpe->last_poll = 0; - cpe->server = res->ai_addr; - cpe->socklen = res->ai_addrlen; + cpe->server = res->ai_addr; + cpe->socklen = res->ai_addrlen; SETGAI(cpe, res); logg("*%s socket tcp:%s:%s added to the pool (slot %d)\n", cpe->local ? "Local" : "Remote", addr ? addr : "localhost", port ? port : "3310", cp->entries); return 0; } - -static int addslot(void) { +static int addslot(void) +{ struct CP_ENTRY *cpe; - if(!(cpe = realloc(cp->pool, (cp->entries + 1) * sizeof(struct CP_ENTRY)))) { - logg("!Out of memory while initializing the connection pool\n"); - cpool_free(); - return 1; + if (!(cpe = realloc(cp->pool, (cp->entries + 1) * sizeof(struct CP_ENTRY)))) { + logg("!Out of memory while initializing the connection pool\n"); + cpool_free(); + return 1; } - if(cp->local_cpe) - cp->local_cpe = (struct CP_ENTRY *)((char *)cp->local_cpe + ((char *)cpe - (char *)cp->pool)); + if (cp->local_cpe) + cp->local_cpe = (struct CP_ENTRY *)((char *)cp->local_cpe + ((char *)cpe - (char *)cp->pool)); memset(&cpe[cp->entries], 0, sizeof(*cpe)); cp->pool = cpe; cp->entries++; return 0; } - /* Probe strategy: - wake up every minute - probe alive if last check > 15 min - probe dead if (last check > 2 min || no clamd available) */ -static void cpool_probe(void) { - unsigned int i, dead=0; +static void cpool_probe(void) +{ + unsigned int i, dead = 0; struct CP_ENTRY *cpe = cp->pool; - time_t now = time(NULL); + time_t now = time(NULL); - for(i=1; i<=cp->entries; i++) { - if((cpe->dead && (cpe->last_poll < now - 120 || !cp->alive)) || cpe->last_poll < now - 15*60*60) { - cpe->last_poll = time(NULL); - nc_ping_entry(cpe); - logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success"); - } - dead += cpe->dead; - cpe++; + for (i = 1; i <= cp->entries; i++) { + if ((cpe->dead && (cpe->last_poll < now - 120 || !cp->alive)) || cpe->last_poll < now - 15 * 60 * 60) { + cpe->last_poll = time(NULL); + nc_ping_entry(cpe); + logg("*Probe for slot %u returned: %s\n", i, cpe->dead ? "failed" : "success"); + } + dead += cpe->dead; + cpe++; } cp->alive = cp->entries - dead; - if(!cp->alive) - logg("^No clamd server appears to be available\n"); + if (!cp->alive) + logg("^No clamd server appears to be available\n"); } - -static void *cpool_mon(_UNUSED_ void *v) { +static void *cpool_mon(_UNUSED_ void *v) +{ pthread_mutex_t conv; pthread_mutex_init(&conv, NULL); pthread_mutex_lock(&conv); - while(!quitting) { - struct timespec t; + while (!quitting) { + struct timespec t; - cpool_probe(); - t.tv_sec = time(NULL) + 60; - t.tv_nsec = 0; - pthread_cond_timedwait(&mon_cond, &conv, &t); + cpool_probe(); + t.tv_sec = time(NULL) + 60; + t.tv_nsec = 0; + pthread_cond_timedwait(&mon_cond, &conv, &t); } pthread_mutex_unlock(&conv); pthread_mutex_destroy(&conv); return NULL; } - -void cpool_init(struct optstruct *opts) { +void cpool_init(struct optstruct *opts) +{ const struct optstruct *opt; int failed = 0; - if(!(cp=calloc(sizeof(*cp), 1))) { - logg("!Out of memory while initializing the connection pool"); - return; + if (!(cp = calloc(sizeof(*cp), 1))) { + logg("!Out of memory while initializing the connection pool"); + return; } cp->local_cpe = NULL; - if((opt = optget(opts, "ClamdSocket"))->enabled) { - while(opt) { - char *socktype = opt->strarg; - - if(addslot()) return; - if(!strncasecmp(socktype, "unix:", 5)) { - failed = cpool_addunix(socktype+5); - } else if(!strncasecmp(socktype, "tcp:", 4)) { - char *port = strrchr(socktype+4, ':'); - if(port) { - *port='\0'; - port++; - } - failed = cpool_addtcp(socktype+4, port); - } else { - logg("!Failed to parse ClamdSocket directive '%s'\n", socktype); - failed = 1; - } - if(failed) break; - opt = opt->nextarg; - } - if(failed) { - cpool_free(); - return; - } - } - - if(!cp->entries) { - logg("!No ClamdSocket specified\n"); - cpool_free(); - return; + if ((opt = optget(opts, "ClamdSocket"))->enabled) { + while (opt) { + char *socktype = opt->strarg; + + if (addslot()) return; + if (!strncasecmp(socktype, "unix:", 5)) { + failed = cpool_addunix(socktype + 5); + } else if (!strncasecmp(socktype, "tcp:", 4)) { + char *port = strrchr(socktype + 4, ':'); + if (port) { + *port = '\0'; + port++; + } + failed = cpool_addtcp(socktype + 4, port); + } else { + logg("!Failed to parse ClamdSocket directive '%s'\n", socktype); + failed = 1; + } + if (failed) break; + opt = opt->nextarg; + } + if (failed) { + cpool_free(); + return; + } + } + + if (!cp->entries) { + logg("!No ClamdSocket specified\n"); + cpool_free(); + return; } quitting = 0; pthread_create(&probe_th, NULL, cpool_mon, NULL); srand(time(NULL)); } - -void cpool_free(void) { +void cpool_free(void) +{ unsigned int i; - if(!quitting) { - logg("*Killing the monitor and stopping\n"); - quitting = 1; - pthread_cond_signal(&mon_cond); - pthread_join(probe_th, NULL); + if (!quitting) { + logg("*Killing the monitor and stopping\n"); + quitting = 1; + pthread_cond_signal(&mon_cond); + pthread_join(probe_th, NULL); } - if(cp) { - if(cp->pool) { - for(i=0; ientries; i++) - FREESRV(cp->pool[i]); - free(cp->pool); - } - free(cp); - cp = NULL; + if (cp) { + if (cp->pool) { + for (i = 0; i < cp->entries; i++) + FREESRV(cp->pool[i]); + free(cp->pool); + } + free(cp); + cp = NULL; } } - -struct CP_ENTRY *cpool_get_rand(int *s) { +struct CP_ENTRY *cpool_get_rand(int *s) +{ unsigned int start, i; struct CP_ENTRY *cpe; - if(cp->alive) { - start = rand() % cp->entries; - for(i=0; ientries; i++) { - cpe = &cp->pool[(i+start) % cp->entries]; - if(cpe->dead) continue; - if(cpe->local && cp->local_cpe && !cp->local_cpe->dead) - cpe = cp->local_cpe; - if((*s = nc_connect_entry(cpe)) == -1) { - cpe->dead = 1; - continue; - } - return cpe; - } + if (cp->alive) { + start = rand() % cp->entries; + for (i = 0; i < cp->entries; i++) { + cpe = &cp->pool[(i + start) % cp->entries]; + if (cpe->dead) continue; + if (cpe->local && cp->local_cpe && !cp->local_cpe->dead) + cpe = cp->local_cpe; + if ((*s = nc_connect_entry(cpe)) == -1) { + cpe->dead = 1; + continue; + } + return cpe; + } } pthread_cond_signal(&mon_cond); return NULL; } - /* * Local Variables: * mode: c diff -Nru clamav-0.101.4+dfsg/clamav-milter/netcode.c clamav-0.102.1+dfsg/clamav-milter/netcode.c --- clamav-0.101.4+dfsg/clamav-milter/netcode.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/netcode.c 2019-11-20 04:42:24.000000000 +0000 @@ -51,7 +51,7 @@ #include "libclamav/others.h" #include "netcode.h" -#define strerror_print(msg) logg(msg": %s\n", cli_strerror(errno, er, sizeof(er))) +#define strerror_print(msg) logg(msg ": %s\n", cli_strerror(errno, er, sizeof(er))) enum { NON_SMTP, @@ -68,359 +68,362 @@ }; struct LOCALNET *lnet = NULL; -char *tempdir = NULL; +char *tempdir = NULL; /* for connect and send */ #define TIMEOUT 30 /* for recv */ long readtimeout; - -static int nc_socket(struct CP_ENTRY *cpe) { +static int nc_socket(struct CP_ENTRY *cpe) +{ int flags, s = socket(cpe->server->sa_family, SOCK_STREAM, 0); char er[256]; if (s == -1) { - strerror_print("!Failed to create socket"); - return -1; + strerror_print("!Failed to create socket"); + return -1; } flags = fcntl(s, F_GETFL, 0); if (flags == -1) { - strerror_print("!fcntl_get failed"); - close(s); - return -1; + strerror_print("!fcntl_get failed"); + close(s); + return -1; } flags |= O_NONBLOCK; if (fcntl(s, F_SETFL, flags) == -1) { - strerror_print("!fcntl_set failed"); - close(s); - return -1; + strerror_print("!fcntl_set failed"); + close(s); + return -1; } return s; } - -static int nc_connect(int s, struct CP_ENTRY *cpe) { +static int nc_connect(int s, struct CP_ENTRY *cpe) +{ time_t timeout = time(NULL) + TIMEOUT; - int res = connect(s, cpe->server, cpe->socklen); + int res = connect(s, cpe->server, cpe->socklen); struct timeval tv; char er[256]; if (!res) return 0; if (errno != EINPROGRESS) { - strerror_print("*connect failed"); - close(s); - return -1; + strerror_print("*connect failed"); + close(s); + return -1; } - tv.tv_sec = TIMEOUT; + tv.tv_sec = TIMEOUT; tv.tv_usec = 0; - while(1) { - fd_set fds; - int s_err; - socklen_t s_len = sizeof(s_err); - - FD_ZERO(&fds); - FD_SET(s, &fds); - res = select(s+1, NULL, &fds, NULL, &tv); - if(res < 1) { - time_t now; - - if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) { - tv.tv_sec = timeout - now; - tv.tv_usec = 0; - continue; - } - logg("*Failed to establish a connection to clamd\n"); - close(s); - return -1; - } - if(getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, (socklen_t *)&s_len) || s_err) { - logg("*Failed to establish a connection to clamd\n"); - close(s); - return -1; - } - return 0; + while (1) { + fd_set fds; + int s_err; + socklen_t s_len = sizeof(s_err); + + FD_ZERO(&fds); + FD_SET(s, &fds); + res = select(s + 1, NULL, &fds, NULL, &tv); + if (res < 1) { + time_t now; + + if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) { + tv.tv_sec = timeout - now; + tv.tv_usec = 0; + continue; + } + logg("*Failed to establish a connection to clamd\n"); + close(s); + return -1; + } + if (getsockopt(s, SOL_SOCKET, SO_ERROR, &s_err, (socklen_t *)&s_len) || s_err) { + logg("*Failed to establish a connection to clamd\n"); + close(s); + return -1; + } + return 0; } } - -int nc_send(int s, const void *buff, size_t len) { +int nc_send(int s, const void *buff, size_t len) +{ char *buf = (char *)buff; - while(len) { - int res = send(s, buf, len, 0); - time_t timeout = time(NULL) + TIMEOUT; - struct timeval tv; - char er[256]; - - if(!res) { - logg("!Connection closed while sending data\n"); - close(s); - return 1; - } - if(res!=-1) { - len-=res; - buf+=res; - continue; - } - if(errno != EAGAIN && errno != EWOULDBLOCK) { - strerror_print("!send failed"); - close(s); - return 1; - } - - tv.tv_sec = TIMEOUT; - tv.tv_usec = 0; - while(1) { - fd_set fds; - - FD_ZERO(&fds); - FD_SET(s, &fds); - res = select(s+1, NULL, &fds, NULL, &tv); - if(res < 1) { - time_t now; - - if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) { - tv.tv_sec = timeout - now; - tv.tv_usec = 0; - continue; - } - logg("!Failed to stream to clamd\n"); - close(s); - return 1; - } - break; - } + while (len) { + int res = send(s, buf, len, 0); + time_t timeout = time(NULL) + TIMEOUT; + struct timeval tv; + char er[256]; + + if (!res) { + logg("!Connection closed while sending data\n"); + close(s); + return 1; + } + if (res != -1) { + len -= res; + buf += res; + continue; + } + if (errno != EAGAIN && errno != EWOULDBLOCK) { + strerror_print("!send failed"); + close(s); + return 1; + } + + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + while (1) { + fd_set fds; + + FD_ZERO(&fds); + FD_SET(s, &fds); + res = select(s + 1, NULL, &fds, NULL, &tv); + if (res < 1) { + time_t now; + + if (res == -1 && errno == EINTR && ((now = time(NULL)) < timeout)) { + tv.tv_sec = timeout - now; + tv.tv_usec = 0; + continue; + } + logg("!Failed to stream to clamd\n"); + close(s); + return 1; + } + break; + } } return 0; } - -int nc_sendmsg(int s, int fd) { +int nc_sendmsg(int s, int fd) +{ struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmsg; int ret; unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; - char dummy[]=""; + char dummy[] = ""; iov[0].iov_base = dummy; - iov[0].iov_len = 1; + iov[0].iov_len = 1; memset(&msg, 0, sizeof(msg)); - msg.msg_control = fdbuf; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_controllen = CMSG_LEN(sizeof(int)); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; + msg.msg_control = fdbuf; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsg) = fd; /* FIXME: nonblock code needed (?) */ - if((ret = sendmsg(s, &msg, 0)) == -1) { - char er[256]; - strerror_print("!clamfi_eom: FD send failed"); - close(s); + if ((ret = sendmsg(s, &msg, 0)) == -1) { + char er[256]; + strerror_print("!clamfi_eom: FD send failed"); + close(s); } return ret; } -char *nc_recv(int s) { - char buf[128], *ret=NULL; +char *nc_recv(int s) +{ + char buf[128], *ret = NULL; time_t now, timeout = time(NULL) + readtimeout; struct timeval tv; fd_set fds; int res; unsigned int len = 0; - while(1) { - now = time(NULL); - if(now >= timeout) { - logg("!Timed out while reading clamd reply\n"); - close(s); - return NULL; - } - tv.tv_sec = timeout - now; - tv.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(s, &fds); - - res = select(s+1, &fds, NULL, NULL, readtimeout ? &tv : NULL); - if(res<1) { - if (res != -1 || errno != EINTR) - timeout = 0; - continue; - } - - res = recv(s, &buf[len], sizeof(buf) - len, 0); - if(!res) { - logg("!Connection closed while reading from socket\n"); - close(s); - return NULL; - } - if(res==-1) { - char er[256]; - if (errno == EAGAIN) - continue; - strerror_print("!recv failed after successful select"); - close(s); - return NULL; - } - len += res; - if(len && buf[len-1] == '\n') break; - if(len >= sizeof(buf)) { - logg("!Overlong reply from clamd\n"); - close(s); - return NULL; - } - } - if(!(ret = (char *)malloc(len+1))) { - logg("!malloc(%d) failed\n", len+1); - close(s); - return NULL; + while (1) { + now = time(NULL); + if (now >= timeout) { + logg("!Timed out while reading clamd reply\n"); + close(s); + return NULL; + } + tv.tv_sec = timeout - now; + tv.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(s, &fds); + + res = select(s + 1, &fds, NULL, NULL, readtimeout ? &tv : NULL); + if (res < 1) { + if (res != -1 || errno != EINTR) + timeout = 0; + continue; + } + + res = recv(s, &buf[len], sizeof(buf) - len, 0); + if (!res) { + logg("!Connection closed while reading from socket\n"); + close(s); + return NULL; + } + if (res == -1) { + char er[256]; + if (errno == EAGAIN) + continue; + strerror_print("!recv failed after successful select"); + close(s); + return NULL; + } + len += res; + if (len && buf[len - 1] == '\n') break; + if (len >= sizeof(buf)) { + logg("!Overlong reply from clamd\n"); + close(s); + return NULL; + } + } + if (!(ret = (char *)malloc(len + 1))) { + logg("!malloc(%d) failed\n", len + 1); + close(s); + return NULL; } memcpy(ret, buf, len); - ret[len]='\0'; + ret[len] = '\0'; return ret; } - -int nc_connect_entry(struct CP_ENTRY *cpe) { +int nc_connect_entry(struct CP_ENTRY *cpe) +{ int s = nc_socket(cpe); - if(s==-1) return -1; + if (s == -1) return -1; return nc_connect(s, cpe) ? -1 : s; } - -void nc_ping_entry(struct CP_ENTRY *cpe) { +void nc_ping_entry(struct CP_ENTRY *cpe) +{ int s = nc_connect_entry(cpe); char *reply; - if(s>=0) { - if(!nc_send(s, "nPING\n", 6) && (reply = nc_recv(s))) { - cpe->dead = strcmp(reply, "PONG\n")!=0; - free(reply); - close(s); - return; - } - close(s); + if (s >= 0) { + if (!nc_send(s, "nPING\n", 6) && (reply = nc_recv(s))) { + cpe->dead = strcmp(reply, "PONG\n") != 0; + free(reply); + close(s); + return; + } + close(s); } cpe->dead = 1; } - -int nc_connect_rand(int *main, int *alt, int *local) { +int nc_connect_rand(int *main, int *alt, int *local) +{ struct CP_ENTRY *cpe = cpool_get_rand(main); - if(!cpe) return 1; + if (!cpe) return 1; *local = (cpe->server->sa_family == AF_UNIX); - if(*local) { - char *unlinkme; - if(cli_gentempfd(tempdir, &unlinkme, alt) != CL_SUCCESS) { - logg("!Failed to create temporary file\n"); - close(*main); - return 1; - } - unlink(unlinkme); - free(unlinkme); - if(nc_send(*main, "nFILDES\n", 8)) { - logg("!FD scan request failed\n"); - close(*alt); - close(*main); - return 1; - } + if (*local) { + char *unlinkme; + if (cli_gentempfd(tempdir, &unlinkme, alt) != CL_SUCCESS) { + logg("!Failed to create temporary file\n"); + close(*main); + return 1; + } + unlink(unlinkme); + free(unlinkme); + if (nc_send(*main, "nFILDES\n", 8)) { + logg("!FD scan request failed\n"); + close(*alt); + close(*main); + return 1; + } } else { - if(nc_send(*main, "nINSTREAM\n", 10)) { - logg("!Failed to communicate with clamd\n"); - close(*main); - return 1; - } + if (nc_send(*main, "nINSTREAM\n", 10)) { + logg("!Failed to communicate with clamd\n"); + close(*main); + return 1; + } } return 0; } - -static int resolve(char *name, uint32_t *family, uint32_t *host) { +static int resolve(char *name, uint32_t *family, uint32_t *host) +{ struct addrinfo hints, *res; - if(!name) { - /* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/ - *family = NON_SMTP; - return 0; + if (!name) { + /* l->basehost[0] = l->basehost[1] = l->basehost[2] = l->basehost[3] = 0; DONT BOTHER*/ + *family = NON_SMTP; + return 0; } memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - if(getaddrinfo(name, NULL, &hints, &res)) { - logg("!Can't resolve LocalNet hostname %s\n", name); - return 1; - } - if(res->ai_addrlen == sizeof(struct sockaddr_in) && res->ai_addr->sa_family == AF_INET) { - struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr; - - *family = INET_HOST; - host[0] = htonl(sa->sin_addr.s_addr); - /* host[1] = host[2] = host[3] = 0; DONT BOTHER*/ - } else if(res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) { - struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr; - unsigned int i, j; - uint32_t u = 0; - - *family = INET6_HOST; - for(i=0, j=0; i<16; i++) { - u += (sa->sin6_addr.s6_addr[i] << (8*j)); - if(++j == 4) { - host[i>>2] = u; - j = u = 0; - } - } + if (getaddrinfo(name, NULL, &hints, &res)) { + logg("!Can't resolve LocalNet hostname %s\n", name); + return 1; + } + if (res->ai_addrlen == sizeof(struct sockaddr_in) && res->ai_addr->sa_family == AF_INET) { + struct sockaddr_in *sa = (struct sockaddr_in *)res->ai_addr; + + *family = INET_HOST; + host[0] = htonl(sa->sin_addr.s_addr); + /* host[1] = host[2] = host[3] = 0; DONT BOTHER*/ + } else if (res->ai_addrlen == sizeof(struct sockaddr_in6) && res->ai_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *sa = (struct sockaddr_in6 *)res->ai_addr; + unsigned int i, j; + uint32_t u = 0; + + *family = INET6_HOST; + for (i = 0, j = 0; i < 16; i++) { + u += (sa->sin6_addr.s6_addr[i] << (8 * j)); + if (++j == 4) { + host[i >> 2] = u; + j = u = 0; + } + } } else { - logg("!Unsupported address type for LocalNet %s\n", name); - freeaddrinfo(res); - return 1; + logg("!Unsupported address type for LocalNet %s\n", name); + freeaddrinfo(res); + return 1; } freeaddrinfo(res); return 0; } - -static struct LOCALNET *localnet(char *name, char *mask) { +static struct LOCALNET *localnet(char *name, char *mask) +{ struct LOCALNET *l = (struct LOCALNET *)malloc(sizeof(*l)); uint32_t nmask; unsigned int i; - if(!l) { - logg("!Out of memory while resolving LocalNet\n"); - return NULL; + if (!l) { + logg("!Out of memory while resolving LocalNet\n"); + return NULL; } - if(resolve(name, &l->family, l->basehost)) { - free(l); - return NULL; + if (resolve(name, &l->family, l->basehost)) { + free(l); + return NULL; } - if(l->family == NON_SMTP) { - l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0x0; - return l; + if (l->family == NON_SMTP) { + l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0x0; + return l; } - if(!mask || !*mask) nmask = 32 + 96*(l->family == INET6_HOST); - else nmask = atoi(mask); + if (!mask || !*mask) + nmask = 32 + 96 * (l->family == INET6_HOST); + else + nmask = atoi(mask); - if((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) { - logg("!Bad netmask '/%s' for LocalNet %s\n", mask, name); - free(l); - return NULL; + if ((l->family == INET6_HOST && nmask > 128) || (l->family == INET_HOST && nmask > 32)) { + logg("!Bad netmask '/%s' for LocalNet %s\n", mask, name); + free(l); + return NULL; } l->mask[0] = l->mask[1] = l->mask[2] = l->mask[3] = 0; - for(i=0; imask[i>>5] |= 1<<(31-(i & 31)); + for (i = 0; i < nmask; i++) + l->mask[i >> 5] |= 1 << (31 - (i & 31)); l->basehost[0] &= l->mask[0]; l->basehost[1] &= l->mask[1]; @@ -430,95 +433,95 @@ return l; } - -static int islocalnet(uint32_t family, uint32_t *host) { - struct LOCALNET* l = lnet; - - if(!l) return 0; - while(l) { - if( - (l->family == family) && - (l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) && - (l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3])) - ) return 1; - l=l->next; +static int islocalnet(uint32_t family, uint32_t *host) +{ + struct LOCALNET *l = lnet; + + if (!l) return 0; + while (l) { + if ( + (l->family == family) && + (l->basehost[0] == (host[0] & l->mask[0])) && (l->basehost[1] == (host[1] & l->mask[1])) && + (l->basehost[2] == (host[2] & l->mask[2])) && (l->basehost[3] == (host[3] & l->mask[3]))) return 1; + l = l->next; } return 0; } - -int islocalnet_name(char *name) { +int islocalnet_name(char *name) +{ uint32_t host[4], family; - if(!lnet) return 0; - if(resolve(name, &family, host)) { - logg("*Cannot resolv %s\n", name); - return 0; + if (!lnet) return 0; + if (resolve(name, &family, host)) { + logg("*Cannot resolv %s\n", name); + return 0; } return islocalnet(family, host); } - -int islocalnet_sock(struct sockaddr *sa) { +int islocalnet_sock(struct sockaddr *sa) +{ uint32_t host[4], family; - if(!lnet) return 0; + if (!lnet) return 0; - if(sa->sa_family == AF_INET) { - struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; + if (sa->sa_family == AF_INET) { + struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; - family = INET_HOST; - host[0] = htonl(sa4->sin_addr.s_addr); - } else if(sa->sa_family == AF_INET6) { - struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; - unsigned int i, j; - uint32_t u = 0; - - family = INET6_HOST; - for(i=0, j=0; i<16; i++) { - u += (sa6->sin6_addr.s6_addr[i] << (8*j)); - if(++j == 4) { - host[i>>2] = u; - j = u = 0; - } - } - } else return 0; + family = INET_HOST; + host[0] = htonl(sa4->sin_addr.s_addr); + } else if (sa->sa_family == AF_INET6) { + struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; + unsigned int i, j; + uint32_t u = 0; + + family = INET6_HOST; + for (i = 0, j = 0; i < 16; i++) { + u += (sa6->sin6_addr.s6_addr[i] << (8 * j)); + if (++j == 4) { + host[i >> 2] = u; + j = u = 0; + } + } + } else + return 0; return islocalnet(family, host); } +void localnets_free(void) +{ + while (lnet) { + struct LOCALNET *l = lnet->next; -void localnets_free(void) { - while(lnet) { - struct LOCALNET *l = lnet->next; - - free(lnet); - lnet = l; - } + free(lnet); + lnet = l; + } } - -int localnets_init(struct optstruct *opts) { +int localnets_init(struct optstruct *opts) +{ const struct optstruct *opt; - if((opt = optget(opts, "LocalNet"))->enabled) { - while(opt) { - char *lnetname = opt->strarg; - struct LOCALNET *l; - char *mask = strrchr(lnetname, *PATHSEP); - - if(mask) { - *mask='\0'; - mask++; - } - if(!strcasecmp(lnetname, "local")) lnetname = NULL; - if((l = localnet(lnetname, mask)) == NULL) { - localnets_free(); - return 1; - } - l->next = lnet; - lnet = l; - opt = opt->nextarg; - } + if ((opt = optget(opts, "LocalNet"))->enabled) { + while (opt) { + char *lnetname = opt->strarg; + struct LOCALNET *l; + char *mask = strrchr(lnetname, *PATHSEP); + + if (mask) { + *mask = '\0'; + mask++; + } + if (!strcasecmp(lnetname, "local")) lnetname = NULL; + if ((l = localnet(lnetname, mask)) == NULL) { + localnets_free(); + return 1; + } + l->next = lnet; + lnet = l; + opt = opt->nextarg; + } } return 0; } diff -Nru clamav-0.101.4+dfsg/clamav-milter/whitelist.c clamav-0.102.1+dfsg/clamav-milter/whitelist.c --- clamav-0.101.4+dfsg/clamav-milter/whitelist.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-milter/whitelist.c 2019-11-20 04:42:24.000000000 +0000 @@ -37,181 +37,184 @@ }; struct WHLST *wfrom = NULL; -struct WHLST *wto = NULL; +struct WHLST *wto = NULL; int skipauth = 0; regex_t authreg; -void whitelist_free(void) { +void whitelist_free(void) +{ struct WHLST *w; - while(wfrom) { - w = wfrom->next; - cli_regfree(&wfrom->preg); - free(wfrom); - wfrom = w; - } - while(wto) { - w = wto->next; - cli_regfree(&wto->preg); - free(wto); - wto = w; + while (wfrom) { + w = wfrom->next; + cli_regfree(&wfrom->preg); + free(wfrom); + wfrom = w; + } + while (wto) { + w = wto->next; + cli_regfree(&wto->preg); + free(wto); + wto = w; } } -int whitelist_init(const char *fname) { +int whitelist_init(const char *fname) +{ char buf[2048]; FILE *f; struct WHLST *w; - if(!(f = fopen(fname, "r"))) { - logg("!Cannot open whitelist file '%s'\n", fname); - return 1; - } - - while(fgets(buf, sizeof(buf), f) != NULL) { - struct WHLST **addto = &wto; - char *ptr = buf; - int len; - - if(*buf == '#' || *buf == ':' || *buf == '!') - continue; - - if(!strncasecmp("From:", buf, 5)) { - ptr+=5; - addto = &wfrom; - } else if (!strncasecmp("To:", buf, 3)) - ptr+=3; - - len = strlen(ptr) - 1; - for(;len>=0; len--) { - if(ptr[len] != '\n' && ptr[len] != '\r') break; - ptr[len] = '\0'; - } - if(!len) continue; - if (!(w = (struct WHLST *)malloc(sizeof(*w)))) { - logg("!Out of memory loading whitelist file\n"); - whitelist_free(); - fclose(f); - return 1; - } - w->next = (*addto); - (*addto) = w; - if (cli_regcomp(&w->preg, ptr, REG_ICASE|REG_NOSUB)) { - logg("!Failed to compile regex '%s' in whitelist file\n", ptr); - whitelist_free(); - fclose(f); - return 1; - } + if (!(f = fopen(fname, "r"))) { + logg("!Cannot open whitelist file '%s'\n", fname); + return 1; + } + + while (fgets(buf, sizeof(buf), f) != NULL) { + struct WHLST **addto = &wto; + char *ptr = buf; + int len; + + if (*buf == '#' || *buf == ':' || *buf == '!') + continue; + + if (!strncasecmp("From:", buf, 5)) { + ptr += 5; + addto = &wfrom; + } else if (!strncasecmp("To:", buf, 3)) + ptr += 3; + + len = strlen(ptr) - 1; + for (; len >= 0; len--) { + if (ptr[len] != '\n' && ptr[len] != '\r') break; + ptr[len] = '\0'; + } + if (!len) continue; + if (!(w = (struct WHLST *)malloc(sizeof(*w)))) { + logg("!Out of memory loading whitelist file\n"); + whitelist_free(); + fclose(f); + return 1; + } + w->next = (*addto); + (*addto) = w; + if (cli_regcomp(&w->preg, ptr, REG_ICASE | REG_NOSUB)) { + logg("!Failed to compile regex '%s' in whitelist file\n", ptr); + whitelist_free(); + fclose(f); + return 1; + } } fclose(f); return 0; } - -int whitelisted(const char *addr, int from) { +int whitelisted(const char *addr, int from) +{ struct WHLST *w; - if(from) w = wfrom; - else w = wto; - - while(w) { - if(!cli_regexec(&w->preg, addr, 0, NULL, 0)) - return 1; - w = w->next; + if (from) + w = wfrom; + else + w = wto; + + while (w) { + if (!cli_regexec(&w->preg, addr, 0, NULL, 0)) + return 1; + w = w->next; } return 0; } - -int smtpauth_init(const char *r) { +int smtpauth_init(const char *r) +{ char *regex = NULL; - if(!strncmp(r, "file:", 5)) { - char buf[2048]; - FILE *f = fopen(r+5, "r"); - int rxsize = 0, rxavail = 0, rxused=0; - - if(!f) { - logg("!Cannot open whitelist file '%s'\n", r+5); - return 1; - } - while(fgets(buf, sizeof(buf), f) != NULL) { - int len; - char *ptr; - - if(*buf == '#' || *buf == ':' || *buf == '!') - continue; - len = strlen(buf) - 1; - for(;len>=0; len--) { - if(buf[len] != '\n' && buf[len] != '\r') break; - buf[len] = '\0'; - } - if(len<=0) continue; - if(len*3+1 > rxavail) { - ptr = regex; - regex = realloc(regex, rxsize + 2048); - if(!regex) { - logg("!Cannot allocate memory for SkipAuthenticated file\n"); - fclose(f); - return 1; - } - rxavail = 2048; - rxsize += 2048; - if(!ptr) { - regex[0] = '^'; - regex[1] = '('; - rxavail -= 2; - rxused = 2; - } - } - ptr = buf; - while(*ptr) { - if((*ptr>='A' && *ptr<='Z') || (*ptr>='a' && *ptr<='z') || (*ptr>='0' && *ptr<='9') || *ptr=='@') { - regex[rxused] = *ptr; - rxused++; - rxavail--; - } else { - regex[rxused] = '['; - regex[rxused+1] = *ptr; - regex[rxused+2] = ']'; - rxused += 3; - rxavail -= 3; - } - ptr++; - } - regex[rxused++] = '|'; - rxavail--; - } - if(rxavail < 4 && !(regex = realloc(regex, rxsize + 4))) { - logg("!Cannot allocate memory for SkipAuthenticated file\n"); - fclose(f); - return 1; - } - regex[rxused-1] = ')'; - regex[rxused] = '$'; - regex[rxused+1] = '\0'; - r = regex; - fclose(f); - } - - if(cli_regcomp(&authreg, r, REG_ICASE|REG_NOSUB|REG_EXTENDED)) { - logg("!Failed to compile regex '%s' for SkipAuthenticated\n", r); - if(regex) free(regex); - return 1; + if (!strncmp(r, "file:", 5)) { + char buf[2048]; + FILE *f = fopen(r + 5, "r"); + int rxsize = 0, rxavail = 0, rxused = 0; + + if (!f) { + logg("!Cannot open whitelist file '%s'\n", r + 5); + return 1; + } + while (fgets(buf, sizeof(buf), f) != NULL) { + int len; + char *ptr; + + if (*buf == '#' || *buf == ':' || *buf == '!') + continue; + len = strlen(buf) - 1; + for (; len >= 0; len--) { + if (buf[len] != '\n' && buf[len] != '\r') break; + buf[len] = '\0'; + } + if (len <= 0) continue; + if (len * 3 + 1 > rxavail) { + ptr = regex; + regex = realloc(regex, rxsize + 2048); + if (!regex) { + logg("!Cannot allocate memory for SkipAuthenticated file\n"); + fclose(f); + return 1; + } + rxavail = 2048; + rxsize += 2048; + if (!ptr) { + regex[0] = '^'; + regex[1] = '('; + rxavail -= 2; + rxused = 2; + } + } + ptr = buf; + while (*ptr) { + if ((*ptr >= 'A' && *ptr <= 'Z') || (*ptr >= 'a' && *ptr <= 'z') || (*ptr >= '0' && *ptr <= '9') || *ptr == '@') { + regex[rxused] = *ptr; + rxused++; + rxavail--; + } else { + regex[rxused] = '['; + regex[rxused + 1] = *ptr; + regex[rxused + 2] = ']'; + rxused += 3; + rxavail -= 3; + } + ptr++; + } + regex[rxused++] = '|'; + rxavail--; + } + if (rxavail < 4 && !(regex = realloc(regex, rxsize + 4))) { + logg("!Cannot allocate memory for SkipAuthenticated file\n"); + fclose(f); + return 1; + } + regex[rxused - 1] = ')'; + regex[rxused] = '$'; + regex[rxused + 1] = '\0'; + r = regex; + fclose(f); + } + + if (cli_regcomp(&authreg, r, REG_ICASE | REG_NOSUB | REG_EXTENDED)) { + logg("!Failed to compile regex '%s' for SkipAuthenticated\n", r); + if (regex) free(regex); + return 1; } - if(regex) free(regex); + if (regex) free(regex); skipauth = 1; return 0; } - -int smtpauthed(const char *login) { - if(skipauth && !cli_regexec(&authreg, login, 0, NULL, 0)) - return 1; +int smtpauthed(const char *login) +{ + if (skipauth && !cli_regexec(&authreg, login, 0, NULL, 0)) + return 1; return 0; } - /* * Local Variables: * mode: c diff -Nru clamav-0.101.4+dfsg/clamav-types.h.in clamav-0.102.1+dfsg/clamav-types.h.in --- clamav-0.101.4+dfsg/clamav-types.h.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-types.h.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,6 +1,6 @@ /* - * Copyright (C) 2015-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * Copyright (C) 2007-2008 Sourcefire, Inc. + * Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2007-2013 Sourcefire, Inc. * * Authors: Tomasz Kojm, Micah Snyder * diff -Nru clamav-0.101.4+dfsg/clamav-version.h.in clamav-0.102.1+dfsg/clamav-version.h.in --- clamav-0.101.4+dfsg/clamav-version.h.in 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamav-version.h.in 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Micah Snyder + * + * @GENERATE_WARNING@ + * + * 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. + */ + +#ifndef CLAMAV_VER_H +#define CLAMAV_VER_H + +/** + * @macro + * Version number of the clamav package release + */ +#define CLAMAV_VERSION "@PACKAGE_VERSION@" + +/** + * @macro + * Numerical representation of the version number of the clamav package + * release. This is a 24 bit number with 8 bits for major number, 8 bits + * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. + */ +#define CLAMAV_VERSION_NUM @PACKAGE_VERSION_NUM@ + +/** + * @macro + * Version number of the clamav library release + */ +#define LIBCLAMAV_VERSION "@LIBCLAMAV_VERSION@" + +/** + * @macro + * Numerical representation of the version number of the libclamav library + * release. This is a 24 bit number with 8 bits for major number, 8 bits + * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. + */ +#define LIBCLAMAV_VERSION_NUM @LIBCLAMAV_VERSION_NUM@ + +/** + * @macro + * Version number of the clamav library release + */ +#define LIBFRESHCLAM_VERSION "@LIBFRESHCLAM_VERSION@" + +/** + * @macro + * Numerical representation of the version number of the libfreshclam library + * release. This is a 24 bit number with 8 bits for major number, 8 bits + * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. + */ +#define LIBFRESHCLAM_VERSION_NUM @LIBFRESHCLAM_VERSION_NUM@ + +#endif /* CLAMAV_VER_H */ diff -Nru clamav-0.101.4+dfsg/clambc/Makefile.in clamav-0.102.1+dfsg/clambc/Makefile.in --- clamav-0.101.4+dfsg/clambc/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clambc/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -81,8 +91,6 @@ target_triplet = @target@ bin_PROGRAMS = clambc$(EXEEXT) subdir = clambc -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -95,6 +103,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -119,7 +128,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -137,7 +147,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -153,9 +162,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -163,6 +172,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -238,6 +248,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -271,12 +282,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -308,8 +324,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -339,7 +353,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -360,6 +378,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -372,6 +391,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -383,6 +405,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -414,6 +437,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -422,6 +447,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -434,6 +460,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -463,6 +490,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -478,6 +506,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ clambc_SOURCES = \ $(top_srcdir)/shared/optparser.c \ $(top_srcdir)/shared/optparser.h \ @@ -506,7 +535,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clambc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clambc/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -881,6 +909,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clambc/bcrun.c clamav-0.102.1+dfsg/clambc/bcrun.c --- clamav-0.101.4+dfsg/clambc/bcrun.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clambc/bcrun.c 2019-11-20 04:42:24.000000000 +0000 @@ -84,37 +84,37 @@ { dbg_state.directory = ctx->directory; if (*ctx->file == '?') - return; + return; switch (event) { - case trace_func: - fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u Entered function %s\n", - dbg_state.file, dbg_state.line, dbg_state.col, - ctx->file, ctx->line, ctx->col, ctx->scope); - dbg_state.scope = ctx->scope; - break; - case trace_param: - fprintf(stderr, "[trace] function parameter:\n"); - return; - case trace_scope: - fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u\n", - dbg_state.file, dbg_state.line, dbg_state.col, - ctx->file, ctx->line, ctx->col); - dbg_state.scope = ctx->scope; - break; - case trace_line: - case trace_col: - if (dbg_state.showline) - cli_bytecode_debug_printsrc(ctx); - else - fprintf(stderr, "[trace] %s:%u:%u\n", - dbg_state.file, dbg_state.line, dbg_state.col); - break; - default: - break; + case trace_func: + fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u Entered function %s\n", + dbg_state.file, dbg_state.line, dbg_state.col, + ctx->file, ctx->line, ctx->col, ctx->scope); + dbg_state.scope = ctx->scope; + break; + case trace_param: + fprintf(stderr, "[trace] function parameter:\n"); + return; + case trace_scope: + fprintf(stderr, "[trace] %s:%u:%u -> %s:%u:%u\n", + dbg_state.file, dbg_state.line, dbg_state.col, + ctx->file, ctx->line, ctx->col); + dbg_state.scope = ctx->scope; + break; + case trace_line: + case trace_col: + if (dbg_state.showline) + cli_bytecode_debug_printsrc(ctx); + else + fprintf(stderr, "[trace] %s:%u:%u\n", + dbg_state.file, dbg_state.line, dbg_state.col); + break; + default: + break; } dbg_state.file = ctx->file; dbg_state.line = ctx->line; - dbg_state.col = ctx->col; + dbg_state.col = ctx->col; } static void tracehook_op(struct cli_bc_ctx *ctx, const char *op) @@ -138,44 +138,44 @@ static uint8_t debug_flag = 0; static void print_src(const char *file) { - char buf[4096]; - int nread, i, found = 0, lcnt = 0; - FILE *f = fopen(file, "r"); - if (!f) { - fprintf(stderr,"Unable to reopen %s\n", file); - return; - } - do { - nread = fread(buf, 1, sizeof(buf), f); - for (i=0;i= 2 && buf[i] == '\n' && buf[i+1] == 'S') { - found = 1; - i+=2; - break; - } - } - } while (!found && (nread == sizeof(buf))); - if (debug_flag) - printf("[clambc] Source code:"); - do { - for (;i+1 0); - fclose(f); + char buf[4096]; + int nread, i, found = 0, lcnt = 0; + FILE *f = fopen(file, "r"); + if (!f) { + fprintf(stderr, "Unable to reopen %s\n", file); + return; + } + do { + nread = fread(buf, 1, sizeof(buf), f); + for (i = 0; i < nread - 1; i++) { + if (buf[i] == '\n') { + lcnt++; + } + /* skip over the logical trigger */ + if (lcnt >= 2 && buf[i] == '\n' && buf[i + 1] == 'S') { + found = 1; + i += 2; + break; + } + } + } while (!found && (nread == sizeof(buf))); + if (debug_flag) + printf("[clambc] Source code:"); + do { + for (; i + 1 < nread; i++) { + if (buf[i] == 'S' || buf[i] == '\n') { + putc('\n', stdout); + continue; + } + putc(((buf[i] & 0xf) | ((buf[i + 1] & 0xf) << 4)), stdout); + i++; + } + if (i == nread - 1 && nread != 1) + fseek(f, -1, SEEK_CUR); + i = 0; + nread = fread(buf, 1, sizeof(buf), f); + } while (nread > 0); + fclose(f); } static uint32_t deadbeefcounts[64] = { 0xdeadbeef, @@ -248,222 +248,229 @@ FILE *f; struct cli_bc *bc; struct cli_bc_ctx *ctx; - int rc, dbgargc, bc_stats=0; + int rc, dbgargc, bc_stats = 0; struct optstruct *opts; const struct optstruct *opt; - unsigned funcid=0, i; + unsigned funcid = 0, i; struct cli_all_bc bcs; int fd = -1; unsigned tracelevel; - if(check_flevel()) - exit(1); + if (check_flevel()) + exit(1); opts = optparse(NULL, argc, argv, 1, OPT_CLAMBC, 0, NULL); if (!opts) { - fprintf(stderr, "ERROR: Can't parse command line options\n"); - exit(1); + fprintf(stderr, "ERROR: Can't parse command line options\n"); + exit(1); } - if(optget(opts, "version")->enabled) { - printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version()); - cl_init(CL_INIT_DEFAULT); - cli_bytecode_printversion(); - optfree(opts); - exit(0); - } - if(optget(opts, "help")->enabled || !opts->filename) { - optfree(opts); - help(); - exit(0); + if (optget(opts, "version")->enabled) { + printf("Clam AntiVirus Bytecode Testing Tool %s\n", get_version()); + cl_init(CL_INIT_DEFAULT); + cli_bytecode_printversion(); + optfree(opts); + exit(0); + } + if (optget(opts, "help")->enabled || !opts->filename) { + optfree(opts); + help(); + exit(0); } f = fopen(opts->filename[0], "r"); if (!f) { - fprintf(stderr, "Unable to load %s\n", argv[1]); - optfree(opts); - exit(2); + fprintf(stderr, "Unable to load %s\n", argv[1]); + optfree(opts); + exit(2); } bc = malloc(sizeof(*bc)); if (!bc) { - fprintf(stderr, "Out of memory\n"); - optfree(opts); - exit(3); + fprintf(stderr, "Out of memory\n"); + optfree(opts); + exit(3); } - if (optget(opts,"debug")->enabled) { - cl_debug(); - debug_flag=1; + if (optget(opts, "debug")->enabled) { + cl_debug(); + debug_flag = 1; } rc = cl_init(CL_INIT_DEFAULT); if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to init libclamav: %s\n", cl_strerror(rc)); - optfree(opts); - exit(4); + fprintf(stderr, "Unable to init libclamav: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); } - dbgargc=1; + dbgargc = 1; while (opts->filename[dbgargc]) dbgargc++; if (dbgargc > 1) - cli_bytecode_debug(dbgargc, opts->filename); + cli_bytecode_debug(dbgargc, opts->filename); if (optget(opts, "force-interpreter")->enabled) { - bcs.engine = NULL; + bcs.engine = NULL; } else { - rc = cli_bytecode_init(&bcs); - if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc)); - optfree(opts); - exit(4); - } + rc = cli_bytecode_init(&bcs); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to init bytecode engine: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); + } } bcs.all_bcs = bc; - bcs.count = 1; + bcs.count = 1; - if((opt = optget(opts, "statistics"))->enabled) { - while(opt) { - if (!strcasecmp(opt->strarg, "bytecode")) - bc_stats=1; - opt = opt->nextarg; + if ((opt = optget(opts, "statistics"))->enabled) { + while (opt) { + if (!strcasecmp(opt->strarg, "bytecode")) + bc_stats = 1; + opt = opt->nextarg; } } rc = cli_bytecode_load(bc, f, NULL, optget(opts, "trust-bytecode")->enabled, bc_stats); if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to load bytecode: %s\n", cl_strerror(rc)); - optfree(opts); - exit(4); + fprintf(stderr, "Unable to load bytecode: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); } fclose(f); if (bc->state == bc_skip) { - fprintf(stderr,"bytecode load skipped\n"); - exit(0); + fprintf(stderr, "bytecode load skipped\n"); + exit(0); } if (debug_flag) - printf("[clambc] Bytecode loaded\n"); + printf("[clambc] Bytecode loaded\n"); if (optget(opts, "info")->enabled) { - cli_bytecode_describe(bc); + cli_bytecode_describe(bc); } else if (optget(opts, "printsrc")->enabled) { print_src(opts->filename[0]); } else if (optget(opts, "printbcir")->enabled) { + unsigned i; cli_bytetype_describe(bc); - cli_bytevalue_describe(bc, 0); - cli_bytefunc_describe(bc, 0); + for (i = 0; i < bc->num_func; ++i) { + printf("########################################################################\n" + "####################### Function id %3u ################################\n" + "########################################################################\n", + i); + cli_bytevalue_describe(bc, i); + cli_bytefunc_describe(bc, i); + } } else { - cli_ctx cctx; - struct cl_engine *engine = cl_engine_new(); - fmap_t *map = NULL; - memset(&cctx, 0, sizeof(cctx)); - if (!engine) { - fprintf(stderr,"Unable to create engine\n"); - optfree(opts); - exit(3); - } - rc = cl_engine_compile(engine); - if (rc) { - fprintf(stderr,"Unable to compile engine: %s\n", cl_strerror(rc)); - optfree(opts); - exit(4); - } - rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK); - if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc)); - optfree(opts); - exit(4); - } - if (debug_flag) - printf("[clambc] Bytecode prepared\n"); - - ctx = cli_bytecode_context_alloc(); - if (!ctx) { - fprintf(stderr,"Out of memory\n"); - exit(3); - } - ctx->ctx = &cctx; - cctx.engine = engine; - cctx.fmap = cli_calloc(sizeof(fmap_t*), engine->maxreclevel+2); - if (!cctx.fmap) { - fprintf(stderr,"Out of memory\n"); - exit(3); - } - memset(&dbg_state, 0, sizeof(dbg_state)); - dbg_state.file = ""; - dbg_state.line = 0; - dbg_state.col = 0; - dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled; - tracelevel = optget(opts, "trace")->numarg; - cli_bytecode_context_set_trace(ctx, tracelevel, - tracehook, - tracehook_op, - tracehook_val, - tracehook_ptr); - - if (opts->filename[1]) { - funcid = atoi(opts->filename[1]); - } - cli_bytecode_context_setfuncid(ctx, bc, funcid); - if (debug_flag) - printf("[clambc] Running bytecode function :%u\n", funcid); - - if (opts->filename[1]) { - i=2; - while (opts->filename[i]) { - rc = cli_bytecode_context_setparam_int(ctx, i-2, atoi(opts->filename[i])); - if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to set param %u: %s\n", i-2, cl_strerror(rc)); - } - i++; - } - } - - if ((opt = optget(opts,"input"))->enabled) { - fd = open(opt->strarg, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno)); - optfree(opts); - exit(5); - } - map = fmap(fd, 0, 0); - if (!map) { - fprintf(stderr, "Unable to map input file %s\n", opt->strarg); - exit(5); - } - rc = cli_bytecode_context_setfile(ctx, map); - if (rc != CL_SUCCESS) { - fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc)); - optfree(opts); - exit(5); - } - } - /* for testing */ - ctx->hooks.match_counts = deadbeefcounts; - ctx->hooks.match_offsets = deadbeefcounts; - rc = cli_bytecode_run(&bcs, bc, ctx); - if (rc != CL_SUCCESS) { - fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc)); - } else { - uint64_t v; - if (debug_flag) - printf("[clambc] Bytecode run finished\n"); - v = cli_bytecode_context_getresult_int(ctx); - if (debug_flag) - printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v); - } - cli_bytecode_context_destroy(ctx); - if (map) - funmap(map); - cl_engine_free(engine); - free(cctx.fmap); + cli_ctx cctx; + struct cl_engine *engine = cl_engine_new(); + fmap_t *map = NULL; + memset(&cctx, 0, sizeof(cctx)); + if (!engine) { + fprintf(stderr, "Unable to create engine\n"); + optfree(opts); + exit(3); + } + rc = cl_engine_compile(engine); + if (rc) { + fprintf(stderr, "Unable to compile engine: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); + } + rc = cli_bytecode_prepare2(engine, &bcs, BYTECODE_ENGINE_MASK); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to prepare bytecode: %s\n", cl_strerror(rc)); + optfree(opts); + exit(4); + } + if (debug_flag) + printf("[clambc] Bytecode prepared\n"); + + ctx = cli_bytecode_context_alloc(); + if (!ctx) { + fprintf(stderr, "Out of memory\n"); + exit(3); + } + ctx->ctx = &cctx; + cctx.engine = engine; + cctx.fmap = cli_calloc(sizeof(fmap_t *), engine->maxreclevel + 2); + if (!cctx.fmap) { + fprintf(stderr, "Out of memory\n"); + exit(3); + } + memset(&dbg_state, 0, sizeof(dbg_state)); + dbg_state.file = ""; + dbg_state.line = 0; + dbg_state.col = 0; + dbg_state.showline = !optget(opts, "no-trace-showsource")->enabled; + tracelevel = optget(opts, "trace")->numarg; + cli_bytecode_context_set_trace(ctx, tracelevel, + tracehook, + tracehook_op, + tracehook_val, + tracehook_ptr); + + if (opts->filename[1]) { + funcid = atoi(opts->filename[1]); + } + cli_bytecode_context_setfuncid(ctx, bc, funcid); + if (debug_flag) + printf("[clambc] Running bytecode function :%u\n", funcid); + + if (opts->filename[1]) { + i = 2; + while (opts->filename[i]) { + rc = cli_bytecode_context_setparam_int(ctx, i - 2, atoi(opts->filename[i])); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to set param %u: %s\n", i - 2, cl_strerror(rc)); + } + i++; + } + } + + if ((opt = optget(opts, "input"))->enabled) { + fd = open(opt->strarg, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Unable to open input file %s: %s\n", opt->strarg, strerror(errno)); + optfree(opts); + exit(5); + } + map = fmap(fd, 0, 0); + if (!map) { + fprintf(stderr, "Unable to map input file %s\n", opt->strarg); + exit(5); + } + rc = cli_bytecode_context_setfile(ctx, map); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to set file %s: %s\n", opt->strarg, cl_strerror(rc)); + optfree(opts); + exit(5); + } + } + /* for testing */ + ctx->hooks.match_counts = deadbeefcounts; + ctx->hooks.match_offsets = deadbeefcounts; + rc = cli_bytecode_run(&bcs, bc, ctx); + if (rc != CL_SUCCESS) { + fprintf(stderr, "Unable to run bytecode: %s\n", cl_strerror(rc)); + } else { + uint64_t v; + if (debug_flag) + printf("[clambc] Bytecode run finished\n"); + v = cli_bytecode_context_getresult_int(ctx); + if (debug_flag) + printf("[clambc] Bytecode returned: 0x%llx\n", (long long)v); + } + cli_bytecode_context_destroy(ctx); + if (map) + funmap(map); + cl_engine_free(engine); + free(cctx.fmap); } cli_bytecode_destroy(bc); cli_bytecode_done(&bcs); free(bc); optfree(opts); if (fd != -1) - close(fd); + close(fd); if (debug_flag) - printf("[clambc] Exiting\n"); - cl_cleanup_crypto(); + printf("[clambc] Exiting\n"); + return 0; } diff -Nru clamav-0.101.4+dfsg/clamconf/Makefile.am clamav-0.102.1+dfsg/clamconf/Makefile.am --- clamav-0.101.4+dfsg/clamconf/Makefile.am 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamconf/Makefile.am 2019-11-20 04:42:24.000000000 +0000 @@ -33,9 +33,9 @@ DEFS = @DEFS@ -DCL_NOTHREADS AM_CPPFLAGS = @CLAMCONF_CPPFLAGS@ -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav\ - @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@\ + @ZLIB_CFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@\ -DBUILD_CPPFLAGS="\"$(CPPFLAGS)\"" -DBUILD_CFLAGS="\"$(CFLAGS)\""\ -DBUILD_CXXFLAGS="\"$(CXXFLAGS)\"" -DBUILD_LDFLAGS="\"$(LDFLAGS)\""\ -DBUILD_CONFIGURE_FLAGS="\"$(BUILD_CONFIGURE_FLAGS)\"" -LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMCONF_LIBS@ @CLAMD_LIBS@ @THREAD_LIBS@ @LIBCLAMAV_LIBS@ +LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMCONF_LIBS@ @CLAMD_LIBS@ @THREAD_LIBS@ @LIBCLAMAV_LIBS@ @ZLIB_LIBS@ CLEANFILES=*.gcda *.gcno diff -Nru clamav-0.101.4+dfsg/clamconf/Makefile.in clamav-0.102.1+dfsg/clamconf/Makefile.in --- clamav-0.101.4+dfsg/clamconf/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamconf/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,17 @@ # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -101,8 +111,6 @@ target_triplet = @target@ bin_PROGRAMS = clamconf$(EXEEXT) subdir = clamconf -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -115,6 +123,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -139,7 +148,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -157,7 +167,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -173,9 +182,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -183,6 +192,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -258,6 +268,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -291,12 +302,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -328,8 +344,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -359,7 +373,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -372,7 +390,7 @@ LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@ LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@ LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@ -LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMCONF_LIBS@ @CLAMD_LIBS@ @THREAD_LIBS@ @LIBCLAMAV_LIBS@ +LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMCONF_LIBS@ @CLAMD_LIBS@ @THREAD_LIBS@ @LIBCLAMAV_LIBS@ @ZLIB_LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ @@ -380,6 +398,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -392,6 +411,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -403,6 +425,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -434,6 +457,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -442,6 +467,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -454,6 +480,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -483,6 +510,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -498,6 +526,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ clamconf_SOURCES = \ $(top_srcdir)/shared/optparser.c \ $(top_srcdir)/shared/optparser.h \ @@ -509,7 +538,7 @@ AM_CFLAGS = @WERR_CFLAGS@ @SSL_CPPFLAGS@ AM_CPPFLAGS = @CLAMCONF_CPPFLAGS@ -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav\ - @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@\ + @ZLIB_CFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@\ -DBUILD_CPPFLAGS="\"$(CPPFLAGS)\"" -DBUILD_CFLAGS="\"$(CFLAGS)\""\ -DBUILD_CXXFLAGS="\"$(CXXFLAGS)\"" -DBUILD_LDFLAGS="\"$(LDFLAGS)\""\ -DBUILD_CONFIGURE_FLAGS="\"$(BUILD_CONFIGURE_FLAGS)\"" @@ -531,7 +560,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamconf/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamconf/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -906,6 +934,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamconf/clamconf.c clamav-0.102.1+dfsg/clamconf/clamconf.c --- clamav-0.101.4+dfsg/clamconf/clamconf.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamconf/clamconf.c 2019-11-20 04:42:24.000000000 +0000 @@ -60,140 +60,140 @@ const char *name; int tool; } cfgfile[] = { - { "clamd.conf", OPT_CLAMD }, - { "freshclam.conf", OPT_FRESHCLAM }, - { "clamav-milter.conf", OPT_MILTER }, - { NULL, 0 } -}; + {"clamd.conf", OPT_CLAMD}, + {"freshclam.conf", OPT_FRESHCLAM}, + {"clamav-milter.conf", OPT_MILTER}, + {NULL, 0}}; static void printopts(struct optstruct *opts, int nondef) { - const struct optstruct *opt; + const struct optstruct *opt; - while(opts) { - if(!opts->name) { - opts = opts->next; - continue; - } - if(clam_options[opts->idx].owner & OPT_DEPRECATED) { - if(opts->active) - printf("*** %s is DEPRECATED ***\n", opts->name); - opts = opts->next; - continue; - } - if(nondef && (opts->numarg == clam_options[opts->idx].numarg) && ((opts->strarg == clam_options[opts->idx].strarg) || (opts->strarg && clam_options[opts->idx].strarg && !strcmp(opts->strarg, clam_options[opts->idx].strarg)))) { - opts = opts->next; - continue; - } - if(!opts->enabled) - printf("%s disabled\n", opts->name); - else switch(clam_options[opts->idx].argtype) { - case CLOPT_TYPE_STRING: - printf("%s = \"%s\"", opts->name, opts->strarg); - opt = opts; - while((opt = opt->nextarg)) - printf(", \"%s\"", opt->strarg); - printf("\n"); - break; - - case CLOPT_TYPE_NUMBER: - case CLOPT_TYPE_SIZE: - printf("%s = \"%lld\"", opts->name, opts->numarg); - opt = opts; - while((opt = opt->nextarg)) - printf(", \"%lld\"", opt->numarg); - printf("\n"); - break; - - case CLOPT_TYPE_BOOL: - printf("%s = \"yes\"\n", opts->name); - break; - - default: - printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", opts->name); - } - opts = opts->next; + while (opts) { + if (!opts->name) { + opts = opts->next; + continue; + } + if (clam_options[opts->idx].owner & OPT_DEPRECATED) { + if (opts->active) + printf("*** %s is DEPRECATED ***\n", opts->name); + opts = opts->next; + continue; + } + if (nondef && (opts->numarg == clam_options[opts->idx].numarg) && ((opts->strarg == clam_options[opts->idx].strarg) || (opts->strarg && clam_options[opts->idx].strarg && !strcmp(opts->strarg, clam_options[opts->idx].strarg)))) { + opts = opts->next; + continue; + } + if (!opts->enabled) + printf("%s disabled\n", opts->name); + else + switch (clam_options[opts->idx].argtype) { + case CLOPT_TYPE_STRING: + printf("%s = \"%s\"", opts->name, opts->strarg); + opt = opts; + while ((opt = opt->nextarg)) + printf(", \"%s\"", opt->strarg); + printf("\n"); + break; + + case CLOPT_TYPE_NUMBER: + case CLOPT_TYPE_SIZE: + printf("%s = \"%lld\"", opts->name, opts->numarg); + opt = opts; + while ((opt = opt->nextarg)) + printf(", \"%lld\"", opt->numarg); + printf("\n"); + break; + + case CLOPT_TYPE_BOOL: + printf("%s = \"yes\"\n", opts->name); + break; + + default: + printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", opts->name); + } + opts = opts->next; } } static int printconf(const char *name) { - int i, j, tool = 0, tokens_count; - char buffer[1025]; - const char *tokens[128]; - const struct clam_option *cpt; - - for(i = 0; cfgfile[i].name; i++) { - if(!strcmp(name, cfgfile[i].name)) { - tool = cfgfile[i].tool; - break; - } - } - if(!tool) { - printf("ERROR: Unknown config file\nAvailable options:"); - for(i = 0; cfgfile[i].name; i++) - printf(" %s", cfgfile[i].name); - printf("\n"); - return 1; + int i, j, tool = 0, tokens_count; + char buffer[1025]; + const char *tokens[128]; + const struct clam_option *cpt; + + for (i = 0; cfgfile[i].name; i++) { + if (!strcmp(name, cfgfile[i].name)) { + tool = cfgfile[i].tool; + break; + } + } + if (!tool) { + printf("ERROR: Unknown config file\nAvailable options:"); + for (i = 0; cfgfile[i].name; i++) + printf(" %s", cfgfile[i].name); + printf("\n"); + return 1; } - printf("##\n## %s - automatically generated by clamconf "VERSION"\n##\n", name); + printf("##\n## %s - automatically generated by clamconf " VERSION "\n##\n", name); printf("\n# Comment out or remove the line below.\nExample\n"); - for(i = 0; clam_options[i].owner; i++) { - cpt = &clam_options[i]; - if(cpt->name && (cpt->owner & tool) && !(cpt->owner & OPT_DEPRECATED) && !(cpt->flags & 4)) { - strncpy(buffer, cpt->description, sizeof(buffer)-1); - buffer[sizeof(buffer)-1] = 0; - tokens_count = cli_strtokenize(buffer, '\n', 128, tokens); - printf("\n"); - for(j = 0; j < tokens_count; j++) - printf("# %s\n", tokens[j]); - - switch(cpt->argtype) { - case CLOPT_TYPE_STRING: - if(cpt->strarg) - printf("# Default: %s\n", cpt->strarg); - else - printf("# Default: disabled\n"); - break; - - case CLOPT_TYPE_NUMBER: - if(cpt->numarg != -1) - printf("# Default: %lld\n", cpt->numarg); - else - printf("# Default: disabled\n"); - break; - - case CLOPT_TYPE_SIZE: - printf("# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)\n# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size\n# in bytes just don't use modifiers.\n"); - if(cpt->numarg != -1) - printf("# Default: %lld\n", cpt->numarg); - else - printf("# Default: disabled\n"); - break; - - case CLOPT_TYPE_BOOL: - if(cpt->numarg != -1) - printf("# Default: %s\n", cpt->numarg ? "yes" : "no"); - else - printf("# Default: disabled\n"); - break; - - default: - printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", cpt->name); - } - - if(cpt->suggested && strchr(cpt->suggested, '\n')) { - strncpy(buffer, cpt->suggested, sizeof(buffer)-1); - buffer[sizeof(buffer)-1] = 0; - tokens_count = cli_strtokenize(buffer, '\n', 128, tokens); - for(j = 0; j < tokens_count; j++) - printf("#%s %s\n", cpt->name, tokens[j]); - } else { - printf("#%s %s\n", cpt->name, cpt->suggested ? cpt->suggested : "ARG"); - } - } + for (i = 0; clam_options[i].owner; i++) { + cpt = &clam_options[i]; + if (cpt->name && (cpt->owner & tool) && !(cpt->owner & OPT_DEPRECATED) && !(cpt->flags & 4)) { + strncpy(buffer, cpt->description, sizeof(buffer) - 1); + buffer[sizeof(buffer) - 1] = 0; + tokens_count = cli_strtokenize(buffer, '\n', 128, tokens); + printf("\n"); + for (j = 0; j < tokens_count; j++) + printf("# %s\n", tokens[j]); + + switch (cpt->argtype) { + case CLOPT_TYPE_STRING: + if (cpt->strarg) + printf("# Default: %s\n", cpt->strarg); + else + printf("# Default: disabled\n"); + break; + + case CLOPT_TYPE_NUMBER: + if (cpt->numarg != -1) + printf("# Default: %lld\n", cpt->numarg); + else + printf("# Default: disabled\n"); + break; + + case CLOPT_TYPE_SIZE: + printf("# You may use 'M' or 'm' for megabytes (1M = 1m = 1048576 bytes)\n# and 'K' or 'k' for kilobytes (1K = 1k = 1024 bytes). To specify the size\n# in bytes just don't use modifiers.\n"); + if (cpt->numarg != -1) + printf("# Default: %lld\n", cpt->numarg); + else + printf("# Default: disabled\n"); + break; + + case CLOPT_TYPE_BOOL: + if (cpt->numarg != -1) + printf("# Default: %s\n", cpt->numarg ? "yes" : "no"); + else + printf("# Default: disabled\n"); + break; + + default: + printf("!!! %s: UNKNOWN INTERNAL TYPE !!!\n", cpt->name); + } + + if (cpt->suggested && strchr(cpt->suggested, '\n')) { + strncpy(buffer, cpt->suggested, sizeof(buffer) - 1); + buffer[sizeof(buffer) - 1] = 0; + tokens_count = cli_strtokenize(buffer, '\n', 128, tokens); + for (j = 0; j < tokens_count; j++) + printf("#%s %s\n", cpt->name, tokens[j]); + } else { + printf("#%s %s\n", cpt->name, cpt->suggested ? cpt->suggested : "ARG"); + } + } } return 0; @@ -219,17 +219,17 @@ { printf("\nPlatform information\n--------------------\n"); printf("uname: %s %s %s %s\n", - env->sysname, env->release, env->version, env->machine); + env->sysname, env->release, env->version, env->machine); - printf("OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE"\n"); + printf("OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE "\n"); #ifdef C_LINUX if (!access("/usr/bin/lsb_release", X_OK)) { - fputs("Full OS version: ", stdout); - fflush(stdout); - if (system("/usr/bin/lsb_release -d -s") == -1) { - perror("failed to determine"); - } + fputs("Full OS version: ", stdout); + fflush(stdout); + if (system("/usr/bin/lsb_release -d -s") == -1) { + perror("failed to determine"); + } } #else /* e.g. Solaris */ @@ -246,24 +246,24 @@ #endif if (strcmp(ZLIB_VERSION, zlibVersion())) - printf("WARNING: zlib version mismatch: %s (%s)\n", ZLIB_VERSION, zlibVersion()); + printf("WARNING: zlib version mismatch: %s (%s)\n", ZLIB_VERSION, zlibVersion()); #ifdef ZLIB_VERNUM printf("zlib version: %s (%s), compile flags: %02lx\n", - ZLIB_VERSION, zlibVersion(), zlibCompileFlags()); + ZLIB_VERSION, zlibVersion(), zlibCompileFlags()); #else /* old zlib w/o zlibCompileFlags() */ printf("zlib version: %s (%s)\n", - ZLIB_VERSION, zlibVersion()); + ZLIB_VERSION, zlibVersion()); #endif if (env->triple[0]) - printf("Triple: %s\n", env->triple); + printf("Triple: %s\n", env->triple); if (env->cpu[0]) - printf("CPU: %s, %s\n", env->cpu, env->big_endian ? "Big-endian" : "Little-endian"); + printf("CPU: %s, %s\n", env->cpu, env->big_endian ? "Big-endian" : "Little-endian"); printf("platform id: 0x%08x%08x%08x\n", - env->platform_id_a, - env->platform_id_b, - env->platform_id_c); + env->platform_id_a, + env->platform_id_b, + env->platform_id_c); } static void print_build(struct cli_environment *env) @@ -273,95 +273,95 @@ printf("\nBuild information\n-----------------\n"); /* Try to print information about some commonly used compilers */ #ifdef __GNUC__ - version = __VERSION__; + version = __VERSION__; #endif switch (env->compiler) { - case compiler_gnuc: - name = "GNU C"; - break; - case compiler_clang: - name = "Clang"; - break; - case compiler_llvm: - name = "LLVM-GCC"; - break; - case compiler_intel: - name = "Intel Compiler"; - break; - case compiler_msc: - name = "Microsoft Visual C++"; - break; - case compiler_sun: - name = "Sun studio"; - break; - default: - name = NULL; + case compiler_gnuc: + name = "GNU C"; + break; + case compiler_clang: + name = "Clang"; + break; + case compiler_llvm: + name = "LLVM-GCC"; + break; + case compiler_intel: + name = "Intel Compiler"; + break; + case compiler_msc: + name = "Microsoft Visual C++"; + break; + case compiler_sun: + name = "Sun studio"; + break; + default: + name = NULL; } if (name) - printf("%s: %s%s(%u.%u.%u)\n", name, - version ? version : "", - version ? " " : "", - env->c_version >> 16, - (env->c_version >> 8)&0xff, - (env->c_version)&0xff); + printf("%s: %s%s(%u.%u.%u)\n", name, + version ? version : "", + version ? " " : "", + env->c_version >> 16, + (env->c_version >> 8) & 0xff, + (env->c_version) & 0xff); cli_printcxxver(); #if defined(BUILD_CPPFLAGS) && defined(BUILD_CFLAGS) && defined(BUILD_CXXFLAGS) && defined(BUILD_LDFLAGS) && defined(BUILD_CONFIGURE_FLAGS) printf("CPPFLAGS: %s\nCFLAGS: %s\nCXXFLAGS: %s\nLDFLAGS: %s\nConfigure: %s\n", - BUILD_CPPFLAGS, BUILD_CFLAGS, BUILD_CXXFLAGS, BUILD_LDFLAGS, - BUILD_CONFIGURE_FLAGS); + BUILD_CPPFLAGS, BUILD_CFLAGS, BUILD_CXXFLAGS, BUILD_LDFLAGS, + BUILD_CONFIGURE_FLAGS); #endif printf("sizeof(void*) = %d\n", env->sizeof_ptr); printf("Engine flevel: %d, dconf: %d\n", - env->functionality_level, - env->dconf_level); + env->functionality_level, + env->dconf_level); } static void print_dbs(const char *dir) { - DIR *dd; - struct dirent *dent; - char *dbfile; - unsigned int flevel = cl_retflevel(), cnt, sigs = 0; - struct cl_cvd *cvd; + DIR *dd; + struct dirent *dent; + char *dbfile; + unsigned int flevel = cl_retflevel(), cnt, sigs = 0; + struct cl_cvd *cvd; - if((dd = opendir(dir)) == NULL) { + if ((dd = opendir(dir)) == NULL) { printf("print_dbs: Can't open directory %s\n", dir); return; } - while((dent = readdir(dd))) { - if(dent->d_ino) { - if(CLI_DBEXT(dent->d_name)) { - dbfile = (char *) malloc(strlen(dent->d_name) + strlen(dir) + 2); - if(!dbfile) { - printf("print_dbs: Can't allocate memory for dbfile\n"); - closedir(dd); - return; - } - sprintf(dbfile, "%s"PATHSEP"%s", dir, dent->d_name); - if(cli_strbcasestr(dbfile, ".cvd") || cli_strbcasestr(dbfile, ".cld")) { - cvd = cl_cvdhead(dbfile); - if(!cvd) { - printf("%s: Can't get information about the database\n", dbfile); - } else { - const time_t t = cvd->stime; - printf("%s: version %u, sigs: %u, built on %s", dent->d_name, cvd->version, cvd->sigs, ctime(&t)); - sigs += cvd->sigs; - if(cvd->fl > flevel) - printf("%s: WARNING: This database requires f-level %u (current f-level: %u)\n", dent->d_name, cvd->fl, flevel); - cl_cvdfree(cvd); - } - } else if(cli_strbcasestr(dbfile, ".cbc")) { - printf("[3rd Party] %s: bytecode\n", dent->d_name); - sigs++; - } else { - cnt = countlines(dbfile); - printf("[3rd Party] %s: %u sig%c\n", dent->d_name, cnt, cnt > 1 ? 's' : ' '); - sigs += cnt; - } - free(dbfile); - } - } + while ((dent = readdir(dd))) { + if (dent->d_ino) { + if (CLI_DBEXT(dent->d_name)) { + dbfile = (char *)malloc(strlen(dent->d_name) + strlen(dir) + 2); + if (!dbfile) { + printf("print_dbs: Can't allocate memory for dbfile\n"); + closedir(dd); + return; + } + sprintf(dbfile, "%s" PATHSEP "%s", dir, dent->d_name); + if (cli_strbcasestr(dbfile, ".cvd") || cli_strbcasestr(dbfile, ".cld")) { + cvd = cl_cvdhead(dbfile); + if (!cvd) { + printf("%s: Can't get information about the database\n", dbfile); + } else { + const time_t t = cvd->stime; + printf("%s: version %u, sigs: %u, built on %s", dent->d_name, cvd->version, cvd->sigs, ctime(&t)); + sigs += cvd->sigs; + if (cvd->fl > flevel) + printf("%s: WARNING: This database requires f-level %u (current f-level: %u)\n", dent->d_name, cvd->fl, flevel); + cl_cvdfree(cvd); + } + } else if (cli_strbcasestr(dbfile, ".cbc")) { + printf("[3rd Party] %s: bytecode\n", dent->d_name); + sigs++; + } else { + cnt = countlines(dbfile); + printf("[3rd Party] %s: %u sig%c\n", dent->d_name, cnt, cnt > 1 ? 's' : ' '); + sigs += cnt; + } + free(dbfile); + } + } } closedir(dd); printf("Total number of signatures: %u\n", sigs); @@ -369,140 +369,140 @@ int main(int argc, char **argv) { - const char *dir; - char path[512], dbdir[512], clamd_dbdir[512], *pt; - struct optstruct *opts, *toolopts; - const struct optstruct *opt; - unsigned int i, j; - struct cli_environment env; + const char *dir; + char path[512], dbdir[512], clamd_dbdir[512], *pt; + struct optstruct *opts, *toolopts; + const struct optstruct *opt; + unsigned int i, j; + struct cli_environment env; opts = optparse(NULL, argc, argv, 1, OPT_CLAMCONF, 0, NULL); - if(!opts) { - printf("ERROR: Can't parse command line options\n"); - return 1; + if (!opts) { + printf("ERROR: Can't parse command line options\n"); + return 1; } - if(optget(opts, "help")->enabled) { - help(); - optfree(opts); - return 0; + if (optget(opts, "help")->enabled) { + help(); + optfree(opts); + return 0; } - if(optget(opts, "version")->enabled) { - printf("Clam AntiVirus Configuration Tool %s\n", get_version()); - optfree(opts); - return 0; + if (optget(opts, "version")->enabled) { + printf("Clam AntiVirus Configuration Tool %s\n", get_version()); + optfree(opts); + return 0; } - if((opt = optget(opts, "generate-config"))->enabled) { - printconf(opt->strarg); - optfree(opts); - return 0; + if ((opt = optget(opts, "generate-config"))->enabled) { + printconf(opt->strarg); + optfree(opts); + return 0; } - dbdir[0] = 0; + dbdir[0] = 0; clamd_dbdir[0] = 0; - dir = optget(opts, "config-dir")->strarg; + dir = optget(opts, "config-dir")->strarg; printf("Checking configuration files in %s\n", dir); - for(i = 0; cfgfile[i].name; i++) { - snprintf(path, sizeof(path), "%s"PATHSEP"%s", dir, cfgfile[i].name); - path[511] = 0; - if(access(path, R_OK)) { - printf("\n%s not found\n", cfgfile[i].name); - continue; - } - printf("\nConfig file: %s\n", cfgfile[i].name); - for(j = 0; j < strlen(cfgfile[i].name) + 13; j++) - printf("-"); - printf("\n"); - toolopts = optparse(path, 0, NULL, 1, cfgfile[i].tool | OPT_DEPRECATED, 0, NULL); - if(!toolopts) - continue; - printopts(toolopts, optget(opts, "non-default")->enabled); - if(cfgfile[i].tool == OPT_FRESHCLAM) { - opt = optget(toolopts, "DatabaseDirectory"); - strncpy(dbdir, opt->strarg, sizeof(dbdir)); - dbdir[sizeof(dbdir) - 1] = 0; - } else if(cfgfile[i].tool == OPT_CLAMD) { - opt = optget(toolopts, "DatabaseDirectory"); - strncpy(clamd_dbdir, opt->strarg, sizeof(clamd_dbdir)); - clamd_dbdir[sizeof(clamd_dbdir) - 1] = 0; - } - optfree(toolopts); + for (i = 0; cfgfile[i].name; i++) { + snprintf(path, sizeof(path), "%s" PATHSEP "%s", dir, cfgfile[i].name); + path[511] = 0; + if (access(path, R_OK)) { + printf("\n%s not found\n", cfgfile[i].name); + continue; + } + printf("\nConfig file: %s\n", cfgfile[i].name); + for (j = 0; j < strlen(cfgfile[i].name) + 13; j++) + printf("-"); + printf("\n"); + toolopts = optparse(path, 0, NULL, 1, cfgfile[i].tool | OPT_DEPRECATED, 0, NULL); + if (!toolopts) + continue; + printopts(toolopts, optget(opts, "non-default")->enabled); + if (cfgfile[i].tool == OPT_FRESHCLAM) { + opt = optget(toolopts, "DatabaseDirectory"); + strncpy(dbdir, opt->strarg, sizeof(dbdir)); + dbdir[sizeof(dbdir) - 1] = 0; + } else if (cfgfile[i].tool == OPT_CLAMD) { + opt = optget(toolopts, "DatabaseDirectory"); + strncpy(clamd_dbdir, opt->strarg, sizeof(clamd_dbdir)); + clamd_dbdir[sizeof(clamd_dbdir) - 1] = 0; + } + optfree(toolopts); } optfree(opts); printf("\nSoftware settings\n-----------------\n"); printf("Version: %s\n", cl_retver()); - if(strcmp(cl_retver(), get_version())) - printf("WARNING: Version mismatch: libclamav=%s, clamconf=%s\n", cl_retver(), get_version()); + if (strcmp(cl_retver(), get_version())) + printf("WARNING: Version mismatch: libclamav=%s, clamconf=%s\n", cl_retver(), get_version()); cl_init(CL_INIT_DEFAULT); printf("Optional features supported: "); #ifdef USE_MPOOL - printf("MEMPOOL "); + printf("MEMPOOL "); #endif #ifdef SUPPORT_IPv6 - printf("IPv6 "); + printf("IPv6 "); #endif #ifdef CLAMUKO - printf("CLAMUKO "); + printf("CLAMUKO "); #endif #ifdef C_BIGSTACK - printf("BIGSTACK "); + printf("BIGSTACK "); #endif #ifdef FRESHCLAM_DNS_FIX - printf("FRESHCLAM_DNS_FIX "); + printf("FRESHCLAM_DNS_FIX "); #endif #ifndef _WIN32 - if (get_fpu_endian() != FPU_ENDIAN_UNKNOWN) + if (get_fpu_endian() != FPU_ENDIAN_UNKNOWN) #endif - printf("AUTOIT_EA06 "); + printf("AUTOIT_EA06 "); #ifdef HAVE_BZLIB_H - printf("BZIP2 "); + printf("BZIP2 "); #endif #ifdef HAVE_LIBXML2 - printf("LIBXML2 "); + printf("LIBXML2 "); #endif #ifdef HAVE_PCRE #if USING_PCRE2 - printf("PCRE2 "); + printf("PCRE2 "); #else - printf("PCRE "); + printf("PCRE "); #endif #endif #ifdef HAVE_ICONV - printf("ICONV "); + printf("ICONV "); #endif #ifdef HAVE_JSON - printf("JSON "); + printf("JSON "); #endif - if(have_rar) - printf("RAR "); + if (have_rar) + printf("RAR "); if (have_clamjit) - printf("JIT"); + printf("JIT"); printf("\n"); - if(!strlen(dbdir)) { - pt = freshdbdir(); - if(pt) { - strncpy(dbdir, pt, sizeof(dbdir)); - free(pt); - } else { - strncpy(dbdir, DATADIR, sizeof(dbdir)); - } - dbdir[sizeof(dbdir) - 1] = 0; + if (!strlen(dbdir)) { + pt = freshdbdir(); + if (pt) { + strncpy(dbdir, pt, sizeof(dbdir)); + free(pt); + } else { + strncpy(dbdir, DATADIR, sizeof(dbdir)); + } + dbdir[sizeof(dbdir) - 1] = 0; } printf("\nDatabase information\n--------------------\n"); printf("Database directory: %s\n", dbdir); - if(strcmp(dbdir, clamd_dbdir)) - printf("WARNING: freshclam.conf and clamd.conf point to different database directories\n"); + if (strcmp(dbdir, clamd_dbdir)) + printf("WARNING: freshclam.conf and clamd.conf point to different database directories\n"); print_dbs(dbdir); cli_detect_environment(&env); print_platform(&env); print_build(&env); - cl_cleanup_crypto(); + return 0; } diff -Nru clamav-0.101.4+dfsg/clamd/Makefile.am clamav-0.102.1+dfsg/clamd/Makefile.am --- clamav-0.101.4+dfsg/clamd/Makefile.am 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/Makefile.am 2019-11-20 04:42:24.000000000 +0000 @@ -48,22 +48,7 @@ scanner.h \ others.c \ others.h \ - shared.h \ - onaccess_others.c \ - onaccess_others.h \ - onaccess_fan.c \ - onaccess_fan.h \ - onaccess_ddd.c \ - onaccess_ddd.h \ - onaccess_hash.c \ - onaccess_hash.h \ - onaccess_scth.c \ - onaccess_scth.h \ - priv_fts.h - -if !SYSTEM_LFS_FTS -clamd_SOURCES += fts.c -endif + shared.h AM_CFLAGS=@WERR_CFLAGS@ diff -Nru clamav-0.101.4+dfsg/clamd/Makefile.in clamav-0.102.1+dfsg/clamd/Makefile.in --- clamav-0.101.4+dfsg/clamd/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -36,7 +36,17 @@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -101,11 +111,7 @@ host_triplet = @host@ target_triplet = @target@ @BUILD_CLAMD_TRUE@sbin_PROGRAMS = clamd$(EXEEXT) -@BUILD_CLAMD_TRUE@@SYSTEM_LFS_FTS_FALSE@am__append_1 = fts.c subdir = clamd -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(srcdir)/clamav-daemon.service.in \ - $(srcdir)/clamav-daemon.socket.in $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -118,6 +124,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -142,7 +149,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -160,7 +168,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -176,9 +183,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -186,6 +193,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -204,23 +212,14 @@ $(top_srcdir)/shared/misc.h clamd.c tcpserver.c tcpserver.h \ localserver.c localserver.h session.c session.h thrmgr.c \ thrmgr.h server-th.c server.h scanner.c scanner.h others.c \ - others.h shared.h onaccess_others.c onaccess_others.h \ - onaccess_fan.c onaccess_fan.h onaccess_ddd.c onaccess_ddd.h \ - onaccess_hash.c onaccess_hash.h onaccess_scth.c \ - onaccess_scth.h priv_fts.h fts.c -@BUILD_CLAMD_TRUE@@SYSTEM_LFS_FTS_FALSE@am__objects_1 = fts.$(OBJEXT) + others.h shared.h @BUILD_CLAMD_TRUE@am_clamd_OBJECTS = output.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ idmef_logging.$(OBJEXT) optparser.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ getopt.$(OBJEXT) misc.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ clamd.$(OBJEXT) tcpserver.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ localserver.$(OBJEXT) session.$(OBJEXT) \ @BUILD_CLAMD_TRUE@ thrmgr.$(OBJEXT) server-th.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ scanner.$(OBJEXT) others.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ onaccess_others.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ onaccess_fan.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ onaccess_ddd.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ onaccess_hash.$(OBJEXT) \ -@BUILD_CLAMD_TRUE@ onaccess_scth.$(OBJEXT) $(am__objects_1) +@BUILD_CLAMD_TRUE@ scanner.$(OBJEXT) others.$(OBJEXT) clamd_OBJECTS = $(am_clamd_OBJECTS) clamd_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) @@ -315,6 +314,9 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(srcdir)/clamav-daemon.service.in \ + $(srcdir)/clamav-daemon.socket.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -348,12 +350,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -385,8 +392,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -416,7 +421,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -437,6 +446,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -449,6 +459,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -460,6 +473,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -491,6 +505,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -499,6 +515,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -511,6 +528,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -540,6 +558,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -555,25 +574,35 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -@BUILD_CLAMD_TRUE@clamd_SOURCES = $(top_srcdir)/shared/output.c \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/output.h \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/idmef_logging.c \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/idmef_logging.h \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/optparser.c \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/optparser.h \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/getopt.c \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/getopt.h \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/misc.c \ -@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/misc.h clamd.c \ -@BUILD_CLAMD_TRUE@ tcpserver.c tcpserver.h localserver.c \ -@BUILD_CLAMD_TRUE@ localserver.h session.c session.h thrmgr.c \ -@BUILD_CLAMD_TRUE@ thrmgr.h server-th.c server.h scanner.c \ -@BUILD_CLAMD_TRUE@ scanner.h others.c others.h shared.h \ -@BUILD_CLAMD_TRUE@ onaccess_others.c onaccess_others.h \ -@BUILD_CLAMD_TRUE@ onaccess_fan.c onaccess_fan.h onaccess_ddd.c \ -@BUILD_CLAMD_TRUE@ onaccess_ddd.h onaccess_hash.c \ -@BUILD_CLAMD_TRUE@ onaccess_hash.h onaccess_scth.c \ -@BUILD_CLAMD_TRUE@ onaccess_scth.h priv_fts.h $(am__append_1) +xmlconfig = @xmlconfig@ +@BUILD_CLAMD_TRUE@clamd_SOURCES = \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/output.c \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/output.h \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/idmef_logging.c \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/idmef_logging.h \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/optparser.c \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/optparser.h \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/getopt.c \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/getopt.h \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/misc.c \ +@BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/misc.h \ +@BUILD_CLAMD_TRUE@ clamd.c \ +@BUILD_CLAMD_TRUE@ tcpserver.c \ +@BUILD_CLAMD_TRUE@ tcpserver.h \ +@BUILD_CLAMD_TRUE@ localserver.c \ +@BUILD_CLAMD_TRUE@ localserver.h \ +@BUILD_CLAMD_TRUE@ session.c \ +@BUILD_CLAMD_TRUE@ session.h \ +@BUILD_CLAMD_TRUE@ thrmgr.c \ +@BUILD_CLAMD_TRUE@ thrmgr.h \ +@BUILD_CLAMD_TRUE@ server-th.c \ +@BUILD_CLAMD_TRUE@ server.h \ +@BUILD_CLAMD_TRUE@ scanner.c \ +@BUILD_CLAMD_TRUE@ scanner.h \ +@BUILD_CLAMD_TRUE@ others.c \ +@BUILD_CLAMD_TRUE@ others.h \ +@BUILD_CLAMD_TRUE@ shared.h + @BUILD_CLAMD_TRUE@AM_CFLAGS = @WERR_CFLAGS@ @BUILD_CLAMD_TRUE@@INSTALL_SYSTEMD_UNITS_TRUE@systemdsystemunit_DATA = clamav-daemon.socket clamav-daemon.service AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @SSL_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ @@ -598,7 +627,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamd/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamd/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -697,16 +725,10 @@ -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/idmef_logging.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/localserver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_ddd.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_fan.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_hash.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_others.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/onaccess_scth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optparser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/others.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@ @@ -1043,6 +1065,8 @@ tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS \ uninstall-systemdsystemunitDATA +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamd/clamav-daemon.service.in clamav-0.102.1+dfsg/clamd/clamav-daemon.service.in --- clamav-0.101.4+dfsg/clamd/clamav-daemon.service.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/clamav-daemon.service.in 2019-11-20 04:42:24.000000000 +0000 @@ -11,6 +11,7 @@ # Reload the database ExecReload=/bin/kill -USR2 $MAINPID StandardOutput=syslog +TimeoutStartSec=420 [Install] WantedBy=multi-user.target diff -Nru clamav-0.101.4+dfsg/clamd/clamd.c clamav-0.102.1+dfsg/clamd/clamd.c --- clamav-0.101.4+dfsg/clamd/clamd.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/clamd.c 2019-11-20 04:42:24.000000000 +0000 @@ -74,10 +74,6 @@ short debug_mode = 0, logok = 0; short foreground = -1; -char hostid[37]; - -char *get_hostid(void *cbdata); -int is_valid_hostid(void); static void help(void) { @@ -118,7 +114,7 @@ { static struct cl_engine *engine = NULL; const struct optstruct *opt; -#ifndef _WIN32 +#ifndef _WIN32 struct passwd *user = NULL; struct sigaction sa; struct rlimit rlim; @@ -127,18 +123,18 @@ const char *dbdir, *cfgfile; char *pua_cats = NULL, *pt; int ret, tcpsock = 0, localsock = 0, min_port, max_port; - unsigned int sigs = 0; - int *lsockets=NULL; + unsigned int sigs = 0; + int *lsockets = NULL; unsigned int nlsockets = 0; unsigned int dboptions = 0; - unsigned int i; + unsigned int i; int j; int num_fd; #ifdef C_LINUX STATBUF sb; #endif - if(check_flevel()) + if (check_flevel()) exit(1); #ifndef _WIN32 @@ -148,45 +144,39 @@ sigaction(SIGUSR2, &sa, NULL); #endif - if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) { + if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMD, 0, NULL)) == NULL) { mprintf("!Can't parse command line options\n"); return 1; } - if(optget(opts, "help")->enabled) { + if (optget(opts, "help")->enabled) { help(); optfree(opts); return 0; } - if(optget(opts, "debug")->enabled) { + if (optget(opts, "debug")->enabled) { #if defined(C_LINUX) /* njh@bandsman.co.uk: create a dump if needed */ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; - if(setrlimit(RLIMIT_CORE, &rlim) < 0) + if (setrlimit(RLIMIT_CORE, &rlim) < 0) perror("setrlimit"); #endif debug_mode = 1; } /* check foreground option from command line to override config file */ - for(j = 0; j < argc; j += 1) - { - if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0)) - { + for (j = 0; j < argc; j += 1) { + if ((memcmp(argv[j], "--foreground", 12) == 0) || (memcmp(argv[j], "-F", 2) == 0)) { /* found */ break; } } - if (j < argc) - { - if(optget(opts, "Foreground")->enabled) - { + if (j < argc) { + if (optget(opts, "Foreground")->enabled) { foreground = 1; - } - else - { + } else { foreground = 0; } } @@ -195,19 +185,19 @@ /* parse the config file */ cfgfile = optget(opts, "config-file")->strarg; - pt = strdup(cfgfile); + pt = strdup(cfgfile); if (pt == NULL) { - fprintf(stderr, "ERROR: Unable to allocate memory for config file\n"); - return 1; + fprintf(stderr, "ERROR: Unable to allocate memory for config file\n"); + return 1; } - if((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) { + if ((opts = optparse(cfgfile, 0, NULL, 1, OPT_CLAMD, 0, opts)) == NULL) { fprintf(stderr, "ERROR: Can't open/parse the config file %s\n", pt); free(pt); return 1; } free(pt); - if(optget(opts, "version")->enabled) { + if (optget(opts, "version")->enabled) { print_version(optget(opts, "DatabaseDirectory")->strarg); optfree(opts); return 0; @@ -215,35 +205,35 @@ /* drop privileges */ #ifndef _WIN32 - if(geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { - if((user = getpwnam(opt->strarg)) == NULL) { + if (geteuid() == 0 && (opt = optget(opts, "User"))->enabled) { + if ((user = getpwnam(opt->strarg)) == NULL) { fprintf(stderr, "ERROR: Can't get information about user %s.\n", opt->strarg); optfree(opts); return 1; } #ifdef HAVE_INITGROUPS - if(initgroups(opt->strarg, user->pw_gid)) { - fprintf(stderr, "ERROR: initgroups() failed.\n"); - optfree(opts); - return 1; - } + if (initgroups(opt->strarg, user->pw_gid)) { + fprintf(stderr, "ERROR: initgroups() failed.\n"); + optfree(opts); + return 1; + } #elif HAVE_SETGROUPS - if(setgroups(1, &user->pw_gid)) { - fprintf(stderr, "ERROR: setgroups() failed.\n"); - optfree(opts); - return 1; - } + if (setgroups(1, &user->pw_gid)) { + fprintf(stderr, "ERROR: setgroups() failed.\n"); + optfree(opts); + return 1; + } #endif - if(setgid(user->pw_gid)) { - fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); + if (setgid(user->pw_gid)) { + fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid); optfree(opts); return 1; } - if(setuid(user->pw_uid)) { - fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); + if (setuid(user->pw_uid)) { + fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid); optfree(opts); return 1; } @@ -251,26 +241,26 @@ #endif /* initialize logger */ - logg_lock = !optget(opts, "LogFileUnlock")->enabled; - logg_time = optget(opts, "LogTime")->enabled; - logok = optget(opts, "LogClean")->enabled; - logg_size = optget(opts, "LogFileMaxSize")->numarg; + logg_lock = !optget(opts, "LogFileUnlock")->enabled; + logg_time = optget(opts, "LogTime")->enabled; + logok = optget(opts, "LogClean")->enabled; + logg_size = optget(opts, "LogFileMaxSize")->numarg; logg_verbose = mprintf_verbose = optget(opts, "LogVerbose")->enabled; if (logg_size) logg_rotate = optget(opts, "LogRotate")->enabled; mprintf_send_timeout = optget(opts, "SendBufTimeout")->numarg; do { /* logger initialized */ - if((opt = optget(opts, "LogFile"))->enabled) { + if ((opt = optget(opts, "LogFile"))->enabled) { char timestr[32]; logg_file = opt->strarg; - if(!cli_is_abspath(logg_file)) { + if (!cli_is_abspath(logg_file)) { fprintf(stderr, "ERROR: LogFile requires full path.\n"); ret = 1; break; } time(&currtime); - if(logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) { + if (logg("#+++ Started at %s", cli_ctime(&currtime, timestr, sizeof(timestr)))) { fprintf(stderr, "ERROR: Can't initialize the internal logger\n"); ret = 1; break; @@ -279,27 +269,27 @@ logg_file = NULL; } - if (optget(opts,"DevLiblog")->enabled) + if (optget(opts, "DevLiblog")->enabled) cl_set_clcb_msg(msg_callback); - if((ret = cl_init(CL_INIT_DEFAULT))) { + if ((ret = cl_init(CL_INIT_DEFAULT))) { logg("!Can't initialize libclamav: %s\n", cl_strerror(ret)); ret = 1; break; } - if(optget(opts, "Debug")->enabled) { + if (optget(opts, "Debug")->enabled) { /* enable debug messages in libclamav */ cl_debug(); logg_verbose = 2; } #if defined(USE_SYSLOG) && !defined(C_AIX) - if(optget(opts, "LogSyslog")->enabled) { + if (optget(opts, "LogSyslog")->enabled) { int fac = LOG_LOCAL6; opt = optget(opts, "LogFacility"); - if((fac = logg_facility(opt->strarg)) == -1) { + if ((fac = logg_facility(opt->strarg)) == -1) { logg("!LogFacility: %s: No such facility.\n", opt->strarg); ret = 1; break; @@ -312,53 +302,52 @@ #ifdef C_LINUX procdev = 0; - if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size) + if (CLAMSTAT("/proc", &sb) != -1 && !sb.st_size) procdev = sb.st_dev; #endif /* check socket type */ - if(optget(opts, "TCPSocket")->enabled) + if (optget(opts, "TCPSocket")->enabled) tcpsock = 1; - if(optget(opts, "LocalSocket")->enabled) + if (optget(opts, "LocalSocket")->enabled) localsock = 1; logg("#Received %d file descriptor(s) from systemd.\n", num_fd); - if(!tcpsock && !localsock && num_fd == 0) { + if (!tcpsock && !localsock && num_fd == 0) { logg("!Please define server type (local and/or TCP).\n"); ret = 1; break; } - logg("#clamd daemon %s (OS: "TARGET_OS_TYPE", ARCH: "TARGET_ARCH_TYPE", CPU: "TARGET_CPU_TYPE")\n", get_version()); + logg("#clamd daemon %s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")\n", get_version()); #ifndef _WIN32 - if(user) + if (user) logg("#Running as user %s (UID %u, GID %u)\n", user->pw_name, user->pw_uid, user->pw_gid); #endif #if defined(RLIMIT_DATA) && defined(C_BSD) if (getrlimit(RLIMIT_DATA, &rlim) == 0) { - /* bb #1941. + /* bb #1941. * On 32-bit FreeBSD if you set ulimit -d to >2GB then mmap() will fail * too soon (after ~120 MB). * Set limit lower than 2G if on 32-bit */ - uint64_t lim = rlim.rlim_cur; - if (sizeof(void*) == 4 && - lim > (1ULL << 31)) { - rlim.rlim_cur = 1ULL << 31; - if (setrlimit(RLIMIT_DATA, &rlim) < 0) - logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno)); - else - logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n"); - } + uint64_t lim = rlim.rlim_cur; + if (sizeof(void *) == 4 && + lim > (1ULL << 31)) { + rlim.rlim_cur = 1ULL << 31; + if (setrlimit(RLIMIT_DATA, &rlim) < 0) + logg("!setrlimit(RLIMIT_DATA) failed: %s\n", strerror(errno)); + else + logg("Running on 32-bit system, and RLIMIT_DATA > 2GB, lowering to 2GB!\n"); + } } #endif - - if(logg_size) + if (logg_size) logg("#Log file size limited to %lld bytes.\n", (long long int)logg_size); else logg("#Log file size limit disabled.\n"); @@ -371,16 +360,7 @@ break; } - /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */ - if(optget(opts, "OnAccessExtraScanning")->enabled) { - logg("*ScanOnAccess: OnAccessExtraScanning was requested, but has " - "been disabled due to a known issue with thread resource " - "cleanup. The OnAccessExtraScanning feature will be " - "re-enabled in a future release when the issue is resolved. " - "For details, see: https://bugzilla.clamav.net/show_bug.cgi?id=12048\n"); - } - - if(!(engine = cl_engine_new())) { + if (!(engine = cl_engine_new())) { logg("!Can't initialize antivirus engine\n"); ret = 1; break; @@ -393,16 +373,16 @@ dbdir = optget(opts, "DatabaseDirectory")->strarg; logg("#Reading databases from %s\n", dbdir); - if(optget(opts, "DetectPUA")->enabled) { + if (optget(opts, "DetectPUA")->enabled) { dboptions |= CL_DB_PUA; - if((opt = optget(opts, "ExcludePUA"))->enabled) { + if ((opt = optget(opts, "ExcludePUA"))->enabled) { dboptions |= CL_DB_PUA_EXCLUDE; i = 0; logg("#Excluded PUA categories:"); - while(opt) { - if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { + while (opt) { + if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); cl_engine_free(engine); ret = 1; @@ -414,19 +394,19 @@ sprintf(pua_cats + i, ".%s", opt->strarg); i += strlen(opt->strarg) + 1; pua_cats[i] = 0; - opt = opt->nextarg; + opt = opt->nextarg; } if (ret) break; logg("#\n"); - pua_cats[i] = '.'; + pua_cats[i] = '.'; pua_cats[i + 1] = 0; } - if((opt = optget(opts, "IncludePUA"))->enabled) { - if(pua_cats) { + if ((opt = optget(opts, "IncludePUA"))->enabled) { + if (pua_cats) { logg("!ExcludePUA and IncludePUA cannot be used at the same time\n"); free(pua_cats); ret = 1; @@ -436,8 +416,8 @@ dboptions |= CL_DB_PUA_INCLUDE; i = 0; logg("#Included PUA categories:"); - while(opt) { - if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { + while (opt) { + if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); ret = 1; break; @@ -448,19 +428,19 @@ sprintf(pua_cats + i, ".%s", opt->strarg); i += strlen(opt->strarg) + 1; pua_cats[i] = 0; - opt = opt->nextarg; + opt = opt->nextarg; } if (ret) break; logg("#\n"); - pua_cats[i] = '.'; + pua_cats[i] = '.'; pua_cats[i + 1] = 0; } - if(pua_cats) { - if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) { + if (pua_cats) { + if ((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) { logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret)); free(pua_cats); ret = 1; @@ -472,14 +452,14 @@ logg("#Not loading PUA signatures.\n"); } - if(optget(opts, "OfficialDatabaseOnly")->enabled) { + if (optget(opts, "OfficialDatabaseOnly")->enabled) { dboptions |= CL_DB_OFFICIAL_ONLY; logg("#Only loading official signatures.\n"); } /* set the temporary dir */ - if((opt = optget(opts, "TemporaryDirectory"))->enabled) { - if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) { + if ((opt = optget(opts, "TemporaryDirectory"))->enabled) { + if ((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) { logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret)); ret = 1; break; @@ -490,20 +470,20 @@ cl_engine_set_clcb_virus_found(engine, clamd_virus_found_cb); - if(optget(opts, "LeaveTemporaryFiles")->enabled) + if (optget(opts, "LeaveTemporaryFiles")->enabled) cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1); - if(optget(opts, "ForceToDisk")->enabled) + if (optget(opts, "ForceToDisk")->enabled) cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1); - if(optget(opts, "PhishingSignatures")->enabled) + if (optget(opts, "PhishingSignatures")->enabled) dboptions |= CL_DB_PHISHING; else logg("#Not loading phishing signatures.\n"); - if(optget(opts,"Bytecode")->enabled) { + if (optget(opts, "Bytecode")->enabled) { dboptions |= CL_DB_BYTECODE; - if((opt = optget(opts,"BytecodeSecurity"))->enabled) { + if ((opt = optget(opts, "BytecodeSecurity"))->enabled) { enum bytecode_security s; if (!strcmp(opt->strarg, "TrustSigned")) { @@ -514,7 +494,7 @@ logg("#Bytecode: Security mode set to \"Paranoid\".\n"); } else { logg("!Unable to parse bytecode security setting:%s\n", - opt->strarg); + opt->strarg); ret = 1; break; } @@ -525,54 +505,54 @@ break; } } - if((opt = optget(opts,"BytecodeUnsigned"))->enabled) { + if ((opt = optget(opts, "BytecodeUnsigned"))->enabled) { dboptions |= CL_DB_BYTECODE_UNSIGNED; logg("#Bytecode: Enabled support for unsigned bytecode.\n"); } - if((opt = optget(opts,"BytecodeMode"))->enabled) { + if ((opt = optget(opts, "BytecodeMode"))->enabled) { enum bytecode_mode mode; if (!strcmp(opt->strarg, "ForceJIT")) mode = CL_BYTECODE_MODE_JIT; - else if(!strcmp(opt->strarg, "ForceInterpreter")) + else if (!strcmp(opt->strarg, "ForceInterpreter")) mode = CL_BYTECODE_MODE_INTERPRETER; - else if(!strcmp(opt->strarg, "Test")) + else if (!strcmp(opt->strarg, "Test")) mode = CL_BYTECODE_MODE_TEST; else mode = CL_BYTECODE_MODE_AUTO; cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode); } - if((opt = optget(opts,"BytecodeTimeout"))->enabled) { + if ((opt = optget(opts, "BytecodeTimeout"))->enabled) { cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg); } } else { logg("#Bytecode support disabled.\n"); } - if(optget(opts,"PhishingScanURLs")->enabled) + if (optget(opts, "PhishingScanURLs")->enabled) dboptions |= CL_DB_PHISHING_URLS; else logg("#Disabling URL based phishing detection.\n"); - if(optget(opts,"DevACOnly")->enabled) { + if (optget(opts, "DevACOnly")->enabled) { logg("#Only using the A-C matcher.\n"); cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1); } - if((opt = optget(opts, "DevACDepth"))->enabled) { + if ((opt = optget(opts, "DevACDepth"))->enabled) { cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, opt->numarg); - logg("#Max A-C depth set to %u\n", (unsigned int) opt->numarg); + logg("#Max A-C depth set to %u\n", (unsigned int)opt->numarg); } - if((ret = cl_load(dbdir, engine, &sigs, dboptions))) { + if ((ret = cl_load(dbdir, engine, &sigs, dboptions))) { logg("!%s\n", cl_strerror(ret)); ret = 1; break; } - if((ret = statinidir_th(dbdir))) { + if ((ret = statinidir_th(dbdir))) { logg("!%s\n", cl_strerror(ret)); ret = 1; break; @@ -584,31 +564,29 @@ logg("#Loaded %u signatures.\n", sigs); /* pcre engine limits - required for cl_engine_compile */ - if((opt = optget(opts, "PCREMatchLimit"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) { + if ((opt = optget(opts, "PCREMatchLimit"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MATCH_LIMIT, opt->numarg))) { logg("!cli_engine_set_num(PCREMatchLimit) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; } } - if((opt = optget(opts, "PCRERecMatchLimit"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) { + if ((opt = optget(opts, "PCRERecMatchLimit"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, opt->numarg))) { logg("!cli_engine_set_num(PCRERecMatchLimit) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; } } - if((ret = cl_engine_compile(engine)) != 0) { + if ((ret = cl_engine_compile(engine)) != 0) { logg("!Database initialization error: %s\n", cl_strerror(ret)); ret = 1; break; } - if(tcpsock || num_fd > 0) { - int *t; - + if (tcpsock || num_fd > 0) { opt = optget(opts, "TCPAddr"); if (opt->enabled) { int breakout = 0; @@ -617,7 +595,7 @@ char *ipaddr = (!strcmp(opt->strarg, "all") ? NULL : opt->strarg); if (tcpserver(&lsockets, &nlsockets, ipaddr, opts) == -1) { - ret = 1; + ret = 1; breakout = 1; break; } @@ -635,7 +613,7 @@ } } #ifndef _WIN32 - if(localsock && num_fd == 0) { + if (localsock && num_fd == 0) { int *t; mode_t sock_mode, umsk = umask(0777); /* socket is created with 000 to avoid races */ @@ -653,14 +631,14 @@ } umask(umsk); /* restore umask */ - if(optget(opts, "LocalSocketGroup")->enabled) { - char *gname = optget(opts, "LocalSocketGroup")->strarg, *end; + if (optget(opts, "LocalSocketGroup")->enabled) { + char *gname = optget(opts, "LocalSocketGroup")->strarg, *end; gid_t sock_gid = strtol(gname, &end, 10); - if(*end) { + if (*end) { struct group *pgrp = getgrnam(gname); - if(!pgrp) { + if (!pgrp) { logg("!Unknown group %s\n", gname); ret = 1; break; @@ -668,18 +646,18 @@ sock_gid = pgrp->gr_gid; } - if(chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) { + if (chown(optget(opts, "LocalSocket")->strarg, -1, sock_gid)) { logg("!Failed to change socket ownership to group %s\n", gname); ret = 1; break; } } - if(optget(opts, "LocalSocketMode")->enabled) { + if (optget(opts, "LocalSocketMode")->enabled) { char *end; sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8); - if(*end) { + if (*end) { logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg); ret = 1; break; @@ -688,7 +666,7 @@ sock_mode = 0777 /* & ~umsk*/; /* conservative default: umask was 0 in clamd < 0.96 */ } - if(chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) { + if (chmod(optget(opts, "LocalSocket")->strarg, sock_mode & 0666)) { logg("!Cannot set socket permission to %s\n", optget(opts, "LocalSocketMode")->strarg); ret = 1; break; @@ -698,8 +676,7 @@ } /* check for local sockets passed by systemd */ - if (num_fd > 0) - { + if (num_fd > 0) { int *t; t = realloc(lsockets, sizeof(int) * (nlsockets + 1)); if (!(t)) { @@ -709,34 +686,26 @@ lsockets = t; lsockets[nlsockets] = localserver(opts); - if (lsockets[nlsockets] == -1) - { + if (lsockets[nlsockets] == -1) { ret = 1; break; - } - else if (lsockets[nlsockets] > 0) - { + } else if (lsockets[nlsockets] > 0) { nlsockets++; } } /* fork into background */ - if (foreground == -1) - { - if (optget(opts, "Foreground")->enabled) - { + if (foreground == -1) { + if (optget(opts, "Foreground")->enabled) { foreground = 1; - } - else - { + } else { foreground = 0; } } - if(foreground == 0) - { -#ifdef C_BSD + if (foreground == 0) { +#ifdef C_BSD /* workaround for OpenBSD bug, see https://wwws.clamav.net/bugzilla/show_bug.cgi?id=885 */ - for(ret=0;(unsigned int)ret 1) ? "s" : ""); for (i = 0; i < nlsockets; i++) { closesocket(lsockets[i]); } #ifndef _WIN32 - if(nlsockets && localsock) { + if (nlsockets && localsock) { opt = optget(opts, "LocalSocket"); - if(unlink(opt->strarg) == -1) + if (unlink(opt->strarg) == -1) logg("!Can't unlink the socket file %s\n", opt->strarg); else logg("Socket file removed.\n"); @@ -804,41 +771,5 @@ logg_close(); optfree(opts); - cl_cleanup_crypto(); - return ret; } - -int is_valid_hostid(void) -{ - int count, i; - - if (strlen(hostid) != 36) - return 0; - - count=0; - for (i=0; i < 36; i++) - if (hostid[i] == '-') - count++; - - if (count != 4) - return 0; - - if (hostid[8] != '-' || hostid[13] != '-' || hostid[18] != '-' || hostid[23] != '-') - return 0; - - return 1; -} - -char *get_hostid(void *cbdata) -{ - UNUSEDPARAM(cbdata); - - if (!strcmp(hostid, "none")) - return NULL; - - if (!is_valid_hostid()) - return strdup(STATS_ANON_UUID); - - return strdup(hostid); -} diff -Nru clamav-0.101.4+dfsg/clamd/fts.c clamav-0.102.1+dfsg/clamd/fts.c --- clamav-0.101.4+dfsg/clamd/fts.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/fts.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1165 +0,0 @@ -/* File tree traversal functions. - Copyright (C) 1994-2015 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; -#endif /* LIBC_SCCS and not lint */ - -#if HAVE_CONFIG_H -#include "clamav-config.h" -#endif - -#if defined(FANOTIFY) && defined(C_LINUX) - -#include -#include -#include -#include -#include -#include "priv_fts.h" -#include -#include -#include - -#define FTS_OPEN _priv_fts_open -#define FTS_CLOSE _priv_fts_close -#define FTS_READ _priv_fts_read -#define FTS_SET _priv_fts_set -#define FTS_CHILDREN _priv_fts_children -#define FTSOBJ FTS -#define FTSENTRY FTSENT -#define INO_T ino_t -#define STAT stat -#define LSTAT lstat - -#define internal_function -# define __set_errno(val) (errno = (val)) - -/* Largest alignment size needed, minus one. - Usually long double is the worst case. */ -#ifndef ALIGNBYTES -#define ALIGNBYTES (__alignof__ (long double) - 1) -#endif -/* Align P to that size. */ -#ifndef ALIGN -#define ALIGN(p) (((unsigned long int) (p) + ALIGNBYTES) & ~ALIGNBYTES) -#endif - -/* Support for the LFS API version. */ -#ifndef FTS_OPEN -#define FTS_OPEN fts_open -#define FTS_CLOSE fts_close -#define FTS_READ fts_read -#define FTS_SET fts_set -#define FTS_CHILDREN fts_children -# define FTSOBJ FTS -# define FTSENTRY FTSENT -# define INO_T ino_t -# define STAT stat -# define LSTAT lstat -#endif - -static FTSENTRY *fts_alloc (FTSOBJ *, const char *, size_t) internal_function; -static FTSENTRY *fts_build (FTSOBJ *, int) internal_function; -static void fts_lfree (FTSENTRY *) internal_function; -static void fts_load (FTSOBJ *, FTSENTRY *) internal_function; -static size_t fts_maxarglen (char * const *) internal_function; -static void fts_padjust (FTSOBJ *, FTSENTRY *) internal_function; -static int fts_palloc (FTSOBJ *, size_t) internal_function; -static FTSENTRY *fts_sort (FTSOBJ *, FTSENTRY *, int) internal_function; -static u_short fts_stat (FTSOBJ *, FTSENTRY *, int) internal_function; -static int fts_safe_changedir (FTSOBJ *, FTSENTRY *, int, const char *) - internal_function; - -#ifndef MAX -#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) -#endif - -#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) - -#define CLR(opt) (sp->fts_options &= ~(opt)) -#define ISSET(opt) (sp->fts_options & (opt)) -#define SET(opt) (sp->fts_options |= (opt)) - -#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) - -/* fts_build flags */ -#define BCHILD 1 /* fts_children */ -#define BNAMES 2 /* fts_children, names only */ -#define BREAD 3 /* fts_read */ - -FTSOBJ * -FTS_OPEN (char * const *argv, int options, - int (*compar) (const FTSENTRY **, const FTSENTRY **)) -{ - FTSOBJ *sp; - FTSENTRY *p, *root; - int nitems; - FTSENTRY *parent = NULL; - FTSENTRY *tmp; - - /* Options check. */ - if (options & ~FTS_OPTIONMASK) { - __set_errno (EINVAL); - return (NULL); - } - - /* Allocate/initialize the stream */ - if ((sp = malloc((u_int)sizeof(FTSOBJ))) == NULL) - return (NULL); - memset(sp, 0, sizeof(FTSOBJ)); - sp->fts_compar = (int (*) (const void *, const void *)) compar; - sp->fts_options = options; - - /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ - if (ISSET(FTS_LOGICAL)) - SET(FTS_NOCHDIR); - - /* - * Start out with 1K of path space, and enough, in any case, - * to hold the user's paths. - */ -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 -#endif - size_t maxarglen = fts_maxarglen(argv); - if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) - goto mem1; - - /* Allocate/initialize root's parent. */ - if (*argv != NULL) { - if ((parent = fts_alloc(sp, "", 0)) == NULL) - goto mem2; - parent->fts_level = FTS_ROOTPARENTLEVEL; - } - - /* Allocate/initialize root(s). */ - for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { - /* Don't allow zero-length paths. */ - size_t len = strlen(*argv); - if (len == 0) { - __set_errno (ENOENT); - goto mem3; - } - - p = fts_alloc(sp, *argv, len); - p->fts_level = FTS_ROOTLEVEL; - p->fts_parent = parent; - p->fts_accpath = p->fts_name; - p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); - - /* Command-line "." and ".." are real directories. */ - if (p->fts_info == FTS_DOT) - p->fts_info = FTS_D; - - /* - * If comparison routine supplied, traverse in sorted - * order; otherwise traverse in the order specified. - */ - if (compar) { - p->fts_link = root; - root = p; - } else { - p->fts_link = NULL; - if (root == NULL) - tmp = root = p; - else { - tmp->fts_link = p; - tmp = p; - } - } - } - if (compar && nitems > 1) - root = fts_sort(sp, root, nitems); - - /* - * Allocate a dummy pointer and make fts_read think that we've just - * finished the node before the root(s); set p->fts_info to FTS_INIT - * so that everything about the "current" node is ignored. - */ - if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) - goto mem3; - sp->fts_cur->fts_link = root; - sp->fts_cur->fts_info = FTS_INIT; - - /* - * If using chdir(2), grab a file descriptor pointing to dot to ensure - * that we can get back here; this could be avoided for some paths, - * but almost certainly not worth the effort. Slashes, symbolic links, - * and ".." are all fairly nasty problems. Note, if we can't get the - * descriptor we run anyway, just more slowly. - */ - if (!ISSET(FTS_NOCHDIR) - && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) - SET(FTS_NOCHDIR); - - return (sp); - -mem3: fts_lfree(root); - free(parent); -mem2: free(sp->fts_path); -mem1: free(sp); - return (NULL); -} - -static void -internal_function -fts_load (FTSOBJ *sp, FTSENTRY *p) -{ - int len; - char *cp; - - /* - * Load the stream structure for the next traversal. Since we don't - * actually enter the directory until after the preorder visit, set - * the fts_accpath field specially so the chdir gets done to the right - * place and the user can access the first node. From fts_open it's - * known that the path will fit. - */ - len = p->fts_pathlen = p->fts_namelen; - memmove(sp->fts_path, p->fts_name, len + 1); - if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { - len = strlen(++cp); - memmove(p->fts_name, cp, len + 1); - p->fts_namelen = len; - } - p->fts_accpath = p->fts_path = sp->fts_path; - sp->fts_dev = p->fts_dev; -} - -int -FTS_CLOSE (FTSOBJ *sp) -{ - FTSENTRY *freep, *p; - int saved_errno; - - /* - * This still works if we haven't read anything -- the dummy structure - * points to the root list, so we step through to the end of the root - * list which has a valid parent pointer. - */ - if (sp->fts_cur) { - for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { - freep = p; - p = p->fts_link != NULL ? p->fts_link : p->fts_parent; - free(freep); - } - free(p); - } - - /* Free up child linked list, sort array, path buffer. */ - if (sp->fts_child) - fts_lfree(sp->fts_child); - free(sp->fts_array); - free(sp->fts_path); - - /* Return to original directory, save errno if necessary. */ - if (!ISSET(FTS_NOCHDIR)) { - saved_errno = fchdir(sp->fts_rfd) ? errno : 0; - (void)close(sp->fts_rfd); - - /* Set errno and return. */ - if (saved_errno != 0) { - /* Free up the stream pointer. */ - free(sp); - __set_errno (saved_errno); - return (-1); - } - } - - /* Free up the stream pointer. */ - free(sp); - return (0); -} - -/* - * Special case of "/" at the end of the path so that slashes aren't - * appended which would cause paths to be written as "....//foo". - */ -#define NAPPEND(p) \ - (p->fts_path[p->fts_pathlen - 1] == '/' \ - ? p->fts_pathlen - 1 : p->fts_pathlen) - -FTSENTRY * -FTS_READ (FTSOBJ *sp) -{ - FTSENTRY *p, *tmp; - int instr; - char *t; - int saved_errno; - - /* If finished or unrecoverable error, return NULL. */ - if (sp->fts_cur == NULL || ISSET(FTS_STOP)) - return (NULL); - - /* Set current node pointer. */ - p = sp->fts_cur; - - /* Save and zero out user instructions. */ - instr = p->fts_instr; - p->fts_instr = FTS_NOINSTR; - - /* Any type of file may be re-visited; re-stat and re-turn. */ - if (instr == FTS_AGAIN) { - p->fts_info = fts_stat(sp, p, 0); - return (p); - } - - /* - * Following a symlink -- SLNONE test allows application to see - * SLNONE and recover. If indirecting through a symlink, have - * keep a pointer to current location. If unable to get that - * pointer, follow fails. - */ - if (instr == FTS_FOLLOW && - (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { - p->fts_info = fts_stat(sp, p, 1); - if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { - if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { - p->fts_errno = errno; - p->fts_info = FTS_ERR; - } else - p->fts_flags |= FTS_SYMFOLLOW; - } - return (p); - } - - /* Directory in pre-order. */ - if (p->fts_info == FTS_D) { - /* If skipped or crossed mount point, do post-order visit. */ - if (instr == FTS_SKIP || - (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { - if (p->fts_flags & FTS_SYMFOLLOW) - (void)close(p->fts_symfd); - if (sp->fts_child) { - fts_lfree(sp->fts_child); - sp->fts_child = NULL; - } - p->fts_info = FTS_DP; - return (p); - } - - /* Rebuild if only read the names and now traversing. */ - if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { - CLR(FTS_NAMEONLY); - fts_lfree(sp->fts_child); - sp->fts_child = NULL; - } - - /* - * Cd to the subdirectory. - * - * If have already read and now fail to chdir, whack the list - * to make the names come out right, and set the parent errno - * so the application will eventually get an error condition. - * Set the FTS_DONTCHDIR flag so that when we logically change - * directories back to the parent we don't do a chdir. - * - * If haven't read do so. If the read fails, fts_build sets - * FTS_STOP or the fts_info field of the node. - */ - if (sp->fts_child != NULL) { - if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { - p->fts_errno = errno; - p->fts_flags |= FTS_DONTCHDIR; - for (p = sp->fts_child; p != NULL; - p = p->fts_link) - p->fts_accpath = - p->fts_parent->fts_accpath; - } - } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { - if (ISSET(FTS_STOP)) - return (NULL); - return (p); - } - p = sp->fts_child; - sp->fts_child = NULL; - sp->fts_cur = p; - goto name; - } - - /* Move to the next node on this level. */ -next: tmp = p; - if ((p = p->fts_link) != NULL) { - sp->fts_cur = p; - free(tmp); - - /* - * If reached the top, return to the original directory (or - * the root of the tree), and load the paths for the next root. - */ - if (p->fts_level == FTS_ROOTLEVEL) { - if (FCHDIR(sp, sp->fts_rfd)) { - SET(FTS_STOP); - return (NULL); - } - fts_load(sp, p); - return p; - } - - /* - * User may have called fts_set on the node. If skipped, - * ignore. If followed, get a file descriptor so we can - * get back if necessary. - */ - if (p->fts_instr == FTS_SKIP) - goto next; - if (p->fts_instr == FTS_FOLLOW) { - p->fts_info = fts_stat(sp, p, 1); - if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { - if ((p->fts_symfd = - open(".", O_RDONLY, 0)) < 0) { - p->fts_errno = errno; - p->fts_info = FTS_ERR; - } else - p->fts_flags |= FTS_SYMFOLLOW; - } - p->fts_instr = FTS_NOINSTR; - } - -name: t = sp->fts_path + NAPPEND(p->fts_parent); - *t++ = '/'; - memmove(t, p->fts_name, p->fts_namelen + 1); - return p; - } - - /* Move up to the parent node. */ - p = tmp->fts_parent; - sp->fts_cur = p; - free(tmp); - - if (p->fts_level == FTS_ROOTPARENTLEVEL) { - /* - * Done; free everything up and set errno to 0 so the user - * can distinguish between error and EOF. - */ - free(p); - __set_errno (0); - return (sp->fts_cur = NULL); - } - - /* NUL terminate the pathname. */ - sp->fts_path[p->fts_pathlen] = '\0'; - - /* - * Return to the parent directory. If at a root node or came through - * a symlink, go back through the file descriptor. Otherwise, cd up - * one directory. - */ - if (p->fts_level == FTS_ROOTLEVEL) { - if (FCHDIR(sp, sp->fts_rfd)) { - SET(FTS_STOP); - return (NULL); - } - } else if (p->fts_flags & FTS_SYMFOLLOW) { - if (FCHDIR(sp, p->fts_symfd)) { - saved_errno = errno; - (void)close(p->fts_symfd); - __set_errno (saved_errno); - SET(FTS_STOP); - return (NULL); - } - (void)close(p->fts_symfd); - } else if (!(p->fts_flags & FTS_DONTCHDIR) && - fts_safe_changedir(sp, p->fts_parent, -1, "..")) { - SET(FTS_STOP); - return (NULL); - } - p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; - return p; -} - -/* - * Fts_set takes the stream as an argument although it's not used in this - * implementation; it would be necessary if anyone wanted to add global - * semantics to fts using fts_set. An error return is allowed for similar - * reasons. - */ -/* ARGSUSED */ -int -FTS_SET (FTSOBJ *sp, FTSENTRY *p, int instr) -{ - if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && - instr != FTS_NOINSTR && instr != FTS_SKIP) { - __set_errno (EINVAL); - return (1); - } - p->fts_instr = instr; - return (0); -} - -FTSENTRY * -FTS_CHILDREN(FTSOBJ *sp, int instr) -{ - FTSENTRY *p; - int fd; - - if (instr != 0 && instr != FTS_NAMEONLY) { - __set_errno (EINVAL); - return (NULL); - } - - /* Set current node pointer. */ - p = sp->fts_cur; - - /* - * Errno set to 0 so user can distinguish empty directory from - * an error. - */ - __set_errno (0); - - /* Fatal errors stop here. */ - if (ISSET(FTS_STOP)) - return (NULL); - - /* Return logical hierarchy of user's arguments. */ - if (p->fts_info == FTS_INIT) - return (p->fts_link); - - /* - * If not a directory being visited in pre-order, stop here. Could - * allow FTS_DNR, assuming the user has fixed the problem, but the - * same effect is available with FTS_AGAIN. - */ - if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) - return (NULL); - - /* Free up any previous child list. */ - if (sp->fts_child != NULL) - fts_lfree(sp->fts_child); - - if (instr == FTS_NAMEONLY) { - SET(FTS_NAMEONLY); - instr = BNAMES; - } else - instr = BCHILD; - - /* - * If using chdir on a relative path and called BEFORE fts_read does - * its chdir to the root of a traversal, we can lose -- we need to - * chdir into the subdirectory, and we don't know where the current - * directory is, so we can't get back so that the upcoming chdir by - * fts_read will work. - */ - if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || - ISSET(FTS_NOCHDIR)) - return (sp->fts_child = fts_build(sp, instr)); - - if ((fd = open(".", O_RDONLY, 0)) < 0) - return (NULL); - sp->fts_child = fts_build(sp, instr); - if (fchdir(fd)) - return (NULL); - (void)close(fd); - return (sp->fts_child); -} - -static inline int -dirent_not_directory(const struct dirent *dp) -{ -#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE - return dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN; -#else - return 0; -#endif -} - -/* - * This is the tricky part -- do not casually change *anything* in here. The - * idea is to build the linked list of entries that are used by fts_children - * and fts_read. There are lots of special cases. - * - * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is - * set and it's a physical walk (so that symbolic links can't be directories), - * we can do things quickly. First, if it's a 4.4BSD file system, the type - * of the file is in the directory entry. Otherwise, we assume that the number - * of subdirectories in a node is equal to the number of links to the parent. - * The former skips all stat calls. The latter skips stat calls in any leaf - * directories and for any files after the subdirectories in the directory have - * been found, cutting the stat calls by about 2/3. - */ -static FTSENTRY * -internal_function -fts_build (FTSOBJ *sp, int type) -{ - struct dirent *dp; - FTSENTRY *p, *head; - int nitems; - FTSENTRY *cur, *tail; - DIR *dirp; - void *oldaddr; - int cderrno, descend, len, level, nlinks, saved_errno, - nostat, doadjust; - size_t maxlen; - char *cp; - - /* Set current node pointer. */ - cur = sp->fts_cur; - - /* - * Open the directory for reading. If this fails, we're done. - * If being called from fts_read, set the fts_info field. - */ -#if defined FTS_WHITEOUT && 0 - if (ISSET(FTS_WHITEOUT)) - oflag = DTF_NODUP|DTF_REWIND; - else - oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND; -#else -# define __opendir2(path, flag) opendir(path) -#endif - if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { - if (type == BREAD) { - cur->fts_info = FTS_DNR; - cur->fts_errno = errno; - } - return (NULL); - } - - /* - * Nlinks is the number of possible entries of type directory in the - * directory if we're cheating on stat calls, 0 if we're not doing - * any stat calls at all, -1 if we're doing stats on everything. - */ - if (type == BNAMES) { - nlinks = 0; - /* Be quiet about nostat, GCC. */ - nostat = 0; - } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { - nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); - nostat = 1; - } else { - nlinks = -1; - nostat = 0; - } - -#ifdef notdef - (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); - (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", - ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); -#endif - /* - * If we're going to need to stat anything or we want to descend - * and stay in the directory, chdir. If this fails we keep going, - * but set a flag so we don't chdir after the post-order visit. - * We won't be able to stat anything, but we can still return the - * names themselves. Note, that since fts_read won't be able to - * chdir into the directory, it will have to return different path - * names than before, i.e. "a/b" instead of "b". Since the node - * has already been visited in pre-order, have to wait until the - * post-order visit to return the error. There is a special case - * here, if there was nothing to stat then it's not an error to - * not be able to stat. This is all fairly nasty. If a program - * needed sorted entries or stat information, they had better be - * checking FTS_NS on the returned nodes. - */ - cderrno = 0; - if (nlinks || type == BREAD) { - if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { - if (nlinks && type == BREAD) - cur->fts_errno = errno; - cur->fts_flags |= FTS_DONTCHDIR; - descend = 0; - cderrno = errno; - (void)closedir(dirp); - dirp = NULL; - } else - descend = 1; - } else - descend = 0; - - /* - * Figure out the max file name length that can be stored in the - * current path -- the inner loop allocates more path as necessary. - * We really wouldn't have to do the maxlen calculations here, we - * could do them in fts_read before returning the path, but it's a - * lot easier here since the length is part of the dirent structure. - * - * If not changing directories set a pointer so that can just append - * each new name into the path. - */ - len = NAPPEND(cur); - if (ISSET(FTS_NOCHDIR)) { - cp = sp->fts_path + len; - *cp++ = '/'; - } else { - /* GCC, you're too verbose. */ - cp = NULL; - } - len++; - maxlen = sp->fts_pathlen - len; - - level = cur->fts_level + 1; - - /* Read the directory, attaching each entry to the `link' pointer. */ - doadjust = 0; - for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { - if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) - continue; - - if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL) - goto mem1; - if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */ - oldaddr = sp->fts_path; - if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) { - /* - * No more memory for path or structures. Save - * errno, free up the current structure and the - * structures already allocated. - */ -mem1: saved_errno = errno; - free(p); - fts_lfree(head); - (void)closedir(dirp); - cur->fts_info = FTS_ERR; - SET(FTS_STOP); - __set_errno (saved_errno); - return (NULL); - } - /* Did realloc() change the pointer? */ - if (oldaddr != sp->fts_path) { - doadjust = 1; - if (ISSET(FTS_NOCHDIR)) - cp = sp->fts_path + len; - } - maxlen = sp->fts_pathlen - len; - } - - if (len + _D_EXACT_NAMLEN (dp) >= USHRT_MAX) { - /* - * In an FTSENT, fts_pathlen is a u_short so it is - * possible to wraparound here. If we do, free up - * the current structure and the structures already - * allocated, then error out with ENAMETOOLONG. - */ - free(p); - fts_lfree(head); - (void)closedir(dirp); - cur->fts_info = FTS_ERR; - SET(FTS_STOP); - __set_errno (ENAMETOOLONG); - return (NULL); - } - p->fts_level = level; - p->fts_parent = sp->fts_cur; - p->fts_pathlen = len + _D_EXACT_NAMLEN (dp); - -#if defined FTS_WHITEOUT && 0 - if (dp->d_type == DT_WHT) - p->fts_flags |= FTS_ISW; -#endif - - /* Unreachable code. cderrno is only ever set to a nonnull - value if dirp is closed at the same time. But then we - cannot enter this loop. */ - if (0 && cderrno) { - if (nlinks) { - p->fts_info = FTS_NS; - p->fts_errno = cderrno; - } else - p->fts_info = FTS_NSOK; - p->fts_accpath = cur->fts_accpath; - } else if (nlinks == 0 - || (nostat && dirent_not_directory(dp))) { - p->fts_accpath = - ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; - p->fts_info = FTS_NSOK; - } else { - /* Build a file name for fts_stat to stat. */ - if (ISSET(FTS_NOCHDIR)) { - p->fts_accpath = p->fts_path; - memmove(cp, p->fts_name, p->fts_namelen + 1); - } else - p->fts_accpath = p->fts_name; - /* Stat it. */ - p->fts_info = fts_stat(sp, p, 0); - - /* Decrement link count if applicable. */ - if (nlinks > 0 && (p->fts_info == FTS_D || - p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) - --nlinks; - } - - /* We walk in directory order so "ls -f" doesn't get upset. */ - p->fts_link = NULL; - if (head == NULL) - head = tail = p; - else { - tail->fts_link = p; - tail = p; - } - ++nitems; - } - if (dirp) - (void)closedir(dirp); - - /* - * If realloc() changed the address of the path, adjust the - * addresses for the rest of the tree and the dir list. - */ - if (doadjust) - fts_padjust(sp, head); - - /* - * If not changing directories, reset the path back to original - * state. - */ - if (ISSET(FTS_NOCHDIR)) { - if (len == sp->fts_pathlen || nitems == 0) - --cp; - *cp = '\0'; - } - - /* - * If descended after called from fts_children or after called from - * fts_read and nothing found, get back. At the root level we use - * the saved fd; if one of fts_open()'s arguments is a relative path - * to an empty directory, we wind up here with no other way back. If - * can't get back, we're done. - */ - if (descend && (type == BCHILD || !nitems) && - (cur->fts_level == FTS_ROOTLEVEL ? - FCHDIR(sp, sp->fts_rfd) : - fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { - cur->fts_info = FTS_ERR; - SET(FTS_STOP); - fts_lfree(head); - return (NULL); - } - - /* If didn't find anything, return NULL. */ - if (!nitems) { - if (type == BREAD) - cur->fts_info = FTS_DP; - fts_lfree(head); - return (NULL); - } - - /* Sort the entries. */ - if (sp->fts_compar && nitems > 1) - head = fts_sort(sp, head, nitems); - return (head); -} - -static u_short -internal_function -fts_stat (FTSOBJ *sp, FTSENTRY *p, int follow) -{ - FTSENTRY *t; - dev_t dev; - INO_T ino; - struct STAT *sbp, sb; - int saved_errno; - - /* If user needs stat info, stat buffer already allocated. */ - sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; - -#if defined FTS_WHITEOUT && 0 - /* check for whiteout */ - if (p->fts_flags & FTS_ISW) { - if (sbp != &sb) { - memset(sbp, '\0', sizeof (*sbp)); - sbp->st_mode = S_IFWHT; - } - return (FTS_W); - } -#endif - - /* - * If doing a logical walk, or application requested FTS_FOLLOW, do - * a stat(2). If that fails, check for a non-existent symlink. If - * fail, set the errno from the stat call. - */ - if (ISSET(FTS_LOGICAL) || follow) { - if (STAT(p->fts_accpath, sbp)) { - saved_errno = errno; - if (!LSTAT(p->fts_accpath, sbp)) { - __set_errno (0); - return (FTS_SLNONE); - } - p->fts_errno = saved_errno; - goto err; - } - } else if (LSTAT(p->fts_accpath, sbp)) { - p->fts_errno = errno; -err: memset(sbp, 0, sizeof(struct STAT)); - return (FTS_NS); - } - - if (S_ISDIR(sbp->st_mode)) { - /* - * Set the device/inode. Used to find cycles and check for - * crossing mount points. Also remember the link count, used - * in fts_build to limit the number of stat calls. It is - * understood that these fields are only referenced if fts_info - * is set to FTS_D. - */ - dev = p->fts_dev = sbp->st_dev; - ino = p->fts_ino = sbp->st_ino; - p->fts_nlink = sbp->st_nlink; - - if (ISDOT(p->fts_name)) - return (FTS_DOT); - - /* - * Cycle detection is done by brute force when the directory - * is first encountered. If the tree gets deep enough or the - * number of symbolic links to directories is high enough, - * something faster might be worthwhile. - */ - for (t = p->fts_parent; - t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) - if (ino == t->fts_ino && dev == t->fts_dev) { - p->fts_cycle = t; - return (FTS_DC); - } - return (FTS_D); - } - if (S_ISLNK(sbp->st_mode)) - return (FTS_SL); - if (S_ISREG(sbp->st_mode)) - return (FTS_F); - return (FTS_DEFAULT); -} - -static FTSENTRY * -internal_function -fts_sort (FTSOBJ *sp, FTSENTRY *head, int nitems) -{ - FTSENTRY **ap, *p; - - /* - * Construct an array of pointers to the structures and call qsort(3). - * Reassemble the array in the order returned by qsort. If unable to - * sort for memory reasons, return the directory entries in their - * current order. Allocate enough space for the current needs plus - * 40 so don't realloc one entry at a time. - */ - if (nitems > sp->fts_nitems) { - FTSENTRY **a; - - sp->fts_nitems = nitems + 40; - if ((a = realloc(sp->fts_array, - (size_t)(sp->fts_nitems * sizeof(FTSENTRY *)))) == NULL) { - free(sp->fts_array); - sp->fts_array = NULL; - sp->fts_nitems = 0; - return (head); - } - sp->fts_array = a; - } - for (ap = sp->fts_array, p = head; p; p = p->fts_link) - *ap++ = p; - qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), sp->fts_compar); - for (head = *(ap = sp->fts_array); --nitems; ++ap) - ap[0]->fts_link = ap[1]; - ap[0]->fts_link = NULL; - return (head); -} - -static FTSENTRY * -internal_function -fts_alloc (FTSOBJ *sp, const char *name, size_t namelen) -{ - FTSENTRY *p; - size_t len; - - /* - * The file name is a variable length array and no stat structure is - * necessary if the user has set the nostat bit. Allocate the FTSENT - * structure, the file name and the stat structure in one chunk, but - * be careful that the stat structure is reasonably aligned. Since the - * fts_name field is declared to be of size 1, the fts_name pointer is - * namelen + 2 before the first possible address of the stat structure. - */ - len = sizeof(FTSENTRY) + namelen; - if (!ISSET(FTS_NOSTAT)) - len += sizeof(struct STAT) + ALIGNBYTES; - if ((p = malloc(len)) == NULL) - return (NULL); - - /* Copy the name and guarantee NUL termination. */ - memmove(p->fts_name, name, namelen); - p->fts_name[namelen] = '\0'; - - if (!ISSET(FTS_NOSTAT)) - p->fts_statp = (struct STAT *)ALIGN(p->fts_name + namelen + 2); - p->fts_namelen = namelen; - p->fts_path = sp->fts_path; - p->fts_errno = 0; - p->fts_flags = 0; - p->fts_instr = FTS_NOINSTR; - p->fts_number = 0; - p->fts_pointer = NULL; - return (p); -} - -static void -internal_function -fts_lfree (FTSENTRY *head) -{ - FTSENTRY *p; - - /* Free a linked list of structures. */ - while ((p = head)) { - head = head->fts_link; - free(p); - } -} - -/* - * Allow essentially unlimited paths; find, rm, ls should all work on any tree. - * Most systems will allow creation of paths much longer than MAXPATHLEN, even - * though the kernel won't resolve them. Add the size (not just what's needed) - * plus 256 bytes so don't realloc the path 2 bytes at a time. - */ -static int -internal_function -fts_palloc (FTSOBJ *sp, size_t more) -{ - char *p; - - sp->fts_pathlen += more + 256; - /* - * Check for possible wraparound. In an FTS, fts_pathlen is - * a signed int but in an FTSENT it is an unsigned short. - * We limit fts_pathlen to USHRT_MAX to be safe in both cases. - */ - if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { - free(sp->fts_path); - sp->fts_path = NULL; - __set_errno (ENAMETOOLONG); - return (1); - } - p = realloc(sp->fts_path, sp->fts_pathlen); - if (p == NULL) { - free(sp->fts_path); - sp->fts_path = NULL; - return 1; - } - sp->fts_path = p; - return 0; -} - -/* - * When the path is realloc'd, have to fix all of the pointers in structures - * already returned. - */ -static void -internal_function -fts_padjust (FTSOBJ *sp, FTSENTRY *head) -{ - FTSENTRY *p; - char *addr = sp->fts_path; - -#define ADJUST(p) do { \ - if ((p)->fts_accpath != (p)->fts_name) { \ - (p)->fts_accpath = \ - (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ - } \ - (p)->fts_path = addr; \ -} while (0) - /* Adjust the current set of children. */ - for (p = sp->fts_child; p; p = p->fts_link) - ADJUST(p); - - /* Adjust the rest of the tree, including the current level. */ - for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { - ADJUST(p); - p = p->fts_link ? p->fts_link : p->fts_parent; - } -} - -static size_t -internal_function -fts_maxarglen (char * const *argv) -{ - size_t len, max; - - for (max = 0; *argv; ++argv) - if ((len = strlen(*argv)) > max) - max = len; - return (max + 1); -} - -/* - * Change to dir specified by fd or p->fts_accpath without getting - * tricked by someone changing the world out from underneath us. - * Assumes p->fts_dev and p->fts_ino are filled in. - */ -static int -internal_function -fts_safe_changedir (FTSOBJ *sp, FTSENTRY *p, int fd, const char *path) -{ - int ret, oerrno, newfd; - struct stat sb; - - newfd = fd; - if (ISSET(FTS_NOCHDIR)) - return (0); - if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) - return (-1); - if (fstat(newfd, &sb)) { - ret = -1; - goto bail; - } - if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { - __set_errno (ENOENT); /* disinformation */ - ret = -1; - goto bail; - } - ret = fchdir(newfd); -bail: - oerrno = errno; - if (fd < 0) - (void)close(newfd); - __set_errno (oerrno); - return (ret); -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/localserver.c clamav-0.102.1+dfsg/clamd/localserver.c --- clamav-0.101.4+dfsg/clamd/localserver.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/localserver.c 2019-11-20 04:42:24.000000000 +0000 @@ -26,7 +26,7 @@ #include #include #include -#ifndef _WIN32 +#ifndef _WIN32 #include #include #endif @@ -58,41 +58,33 @@ int localserver(const struct optstruct *opts) { - struct sockaddr_un server; - int sockfd = 0, backlog; - STATBUF foo; - char *estr; - char *sockdir; - char *pos; - struct stat sb; - int cnt; + struct sockaddr_un server; + int sockfd = 0, backlog; + STATBUF foo; + char *estr; + char *sockdir; + char *pos; + struct stat sb; + int cnt; int num_fd = sd_listen_fds(0); - if (num_fd > 2) - { + if (num_fd > 2) { logg("!LOCAL: Received more than two file descriptors from systemd.\n"); return -1; - } - else if (num_fd > 0) - { + } else if (num_fd > 0) { /* use socket passed by systemd */ int i; - for(i = 0; i < num_fd; i += 1) - { + for (i = 0; i < num_fd; i += 1) { sockfd = SD_LISTEN_FDS_START + i; - if (sd_is_socket(sockfd, AF_UNIX, SOCK_STREAM, 1) == 1) - { + if (sd_is_socket(sockfd, AF_UNIX, SOCK_STREAM, 1) == 1) { /* correct socket */ break; - } - else - { + } else { /* wrong socket */ sockfd = -2; } } - if (sockfd == -2) - { + if (sockfd == -2) { logg("#LOCAL: No local AF_UNIX SOCK_STREAM socket received from systemd.\n"); return -2; } @@ -100,22 +92,21 @@ return sockfd; } /* create socket */ - memset((char *) &server, 0, sizeof(server)); + memset((char *)&server, 0, sizeof(server)); server.sun_family = AF_UNIX; strncpy(server.sun_path, optget(opts, "LocalSocket")->strarg, sizeof(server.sun_path)); - server.sun_path[sizeof(server.sun_path)-1]='\0'; + server.sun_path[sizeof(server.sun_path) - 1] = '\0'; pos = NULL; - if ((pos = strstr(server.sun_path, "/")) && (pos = strstr(((char*) pos + 1), "/"))) { - cnt = 0; + if ((pos = strstr(server.sun_path, "/")) && (pos = strstr(((char *)pos + 1), "/"))) { + cnt = 0; sockdir = NULL; - pos = server.sun_path + strlen(server.sun_path); + pos = server.sun_path + strlen(server.sun_path); while (pos != server.sun_path) { if (*pos == '/') { - sockdir = cli_strndup(server.sun_path, strlen(server.sun_path) - cnt); + sockdir = CLI_STRNDUP(server.sun_path, strlen(server.sun_path) - cnt); break; - } - else { + } else { pos--; cnt++; } @@ -124,11 +115,11 @@ if (stat(sockdir, &sb)) { if (errno == ENOENT) { mode_t sock_mode; - if(optget(opts, "LocalSocketMode")->enabled) { + if (optget(opts, "LocalSocketMode")->enabled) { char *end; sock_mode = strtol(optget(opts, "LocalSocketMode")->strarg, &end, 8); - if(*end) { + if (*end) { logg("!Invalid LocalSocketMode %s\n", optget(opts, "LocalSocketMode")->strarg); free(sockdir); return -1; @@ -142,8 +133,7 @@ if (errno == ENOENT) { logg("!LOCAL: Ensure parent directory exists.\n"); } - } - else { + } else { logg("Localserver: Creating socket directory: %s\n", sockdir); } } @@ -151,44 +141,44 @@ free(sockdir); } - if((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - estr = strerror(errno); - logg("!LOCAL: Socket allocation error: %s\n", estr); - return -1; + if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + estr = strerror(errno); + logg("!LOCAL: Socket allocation error: %s\n", estr); + return -1; } - if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) { - if(errno == EADDRINUSE) { - if(connect(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) >= 0) { - logg("!LOCAL: Socket file %s is in use by another process.\n", server.sun_path); - close(sockfd); - return -1; - } - if(optget(opts, "FixStaleSocket")->enabled) { - logg("#LOCAL: Removing stale socket file %s\n", server.sun_path); - if(unlink(server.sun_path) == -1) { - estr = strerror(errno); - logg("!LOCAL: Socket file %s could not be removed: %s\n", server.sun_path, estr); - close(sockfd); - return -1; - } - if(bind(sockfd, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) == -1) { - estr = strerror(errno); - logg("!LOCAL: Socket file %s could not be bound: %s (unlink tried)\n", server.sun_path, estr); - close(sockfd); - return -1; - } - } else if(CLAMSTAT(server.sun_path, &foo) != -1) { - logg("!LOCAL: Socket file %s exists. Either remove it, or configure a different one.\n", server.sun_path); - close(sockfd); - return -1; - } - } else { - estr = strerror(errno); - logg("!LOCAL: Socket file %s could not be bound: %s\n", server.sun_path, estr); - close(sockfd); - return -1; - } + if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) == -1) { + if (errno == EADDRINUSE) { + if (connect(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) >= 0) { + logg("!LOCAL: Socket file %s is in use by another process.\n", server.sun_path); + close(sockfd); + return -1; + } + if (optget(opts, "FixStaleSocket")->enabled) { + logg("#LOCAL: Removing stale socket file %s\n", server.sun_path); + if (unlink(server.sun_path) == -1) { + estr = strerror(errno); + logg("!LOCAL: Socket file %s could not be removed: %s\n", server.sun_path, estr); + close(sockfd); + return -1; + } + if (bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_un)) == -1) { + estr = strerror(errno); + logg("!LOCAL: Socket file %s could not be bound: %s (unlink tried)\n", server.sun_path, estr); + close(sockfd); + return -1; + } + } else if (CLAMSTAT(server.sun_path, &foo) != -1) { + logg("!LOCAL: Socket file %s exists. Either remove it, or configure a different one.\n", server.sun_path); + close(sockfd); + return -1; + } + } else { + estr = strerror(errno); + logg("!LOCAL: Socket file %s could not be bound: %s\n", server.sun_path, estr); + close(sockfd); + return -1; + } } logg("#LOCAL: Unix socket file %s\n", server.sun_path); @@ -196,11 +186,11 @@ backlog = optget(opts, "MaxConnectionQueueLength")->numarg; logg("#LOCAL: Setting connection queue length to %d\n", backlog); - if(listen(sockfd, backlog) == -1) { - estr = strerror(errno); - logg("!LOCAL: listen() error: %s\n", estr); - close(sockfd); - return -1; + if (listen(sockfd, backlog) == -1) { + estr = strerror(errno); + logg("!LOCAL: listen() error: %s\n", estr); + close(sockfd); + return -1; } return sockfd; diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_ddd.c clamav-0.102.1+dfsg/clamd/onaccess_ddd.c --- clamav-0.101.4+dfsg/clamd/onaccess_ddd.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_ddd.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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 - -#if defined(FANOTIFY) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "onaccess_fan.h" -#include "onaccess_hash.h" -#include "onaccess_ddd.h" -#include "onaccess_scth.h" - -#include "libclamav/clamav.h" -#include "libclamav/scanners.h" - -#include "shared/optparser.h" -#include "shared/output.h" - -#include "server.h" -#include "others.h" -#include "scanner.h" - -static int onas_ddd_init_ht(uint32_t ht_size); -static int onas_ddd_init_wdlt(uint64_t nwatches); -static int onas_ddd_grow_wdlt(); - -static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask); -static int onas_ddd_watch_hierarchy(const char* pathname, size_t len, int fd, uint64_t mask, uint32_t type); -static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd); -static int onas_ddd_unwatch_hierarchy(const char* pathname, size_t len, int fd, uint32_t type); - -static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask); -static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask); -static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd); -static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg, const char *path, const char *child_path, const struct inotify_event *event, int wd); -static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options); - -static void onas_ddd_exit(int sig); - -/* TODO: Unglobalize these. */ -static struct onas_ht *ddd_ht; -static char **wdlt; -static uint32_t wdlt_len; -static int onas_in_fd; - -static int onas_ddd_init_ht(uint32_t ht_size) { - - if (ht_size <= 0) - ht_size = ONAS_DEFAULT_HT_SIZE; - - return onas_ht_init(&ddd_ht, ht_size); -} - -static int onas_ddd_init_wdlt(uint64_t nwatches) { - - if (nwatches <= 0) return CL_EARG; - - wdlt = (char **) cli_calloc(nwatches << 1, sizeof(char*)); - if (!wdlt) return CL_EMEM; - - wdlt_len = nwatches << 1; - - return CL_SUCCESS; -} - -static int onas_ddd_grow_wdlt() { - - char **ptr = NULL; - - ptr = (char **) cli_realloc(wdlt, wdlt_len << 1); - if (ptr) { - wdlt = ptr; - memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1)); - } else { - return CL_EMEM; - } - - wdlt_len <<= 1; - - return CL_SUCCESS; -} - - -/* TODO: Support configuration for changing/setting number of inotify watches. */ -int onas_ddd_init(uint64_t nwatches, size_t ht_size) { - - const char* nwatch_file = "/proc/sys/fs/inotify/max_user_watches"; - int nwfd = 0; - int ret = 0; - char nwatch_str[MAX_WATCH_LEN]; - char *p = NULL; - nwatches = 0; - - nwfd = open(nwatch_file, O_RDONLY); - if (nwfd < 0) return CL_EOPEN; - - ret = read(nwfd, nwatch_str, MAX_WATCH_LEN); - close(nwfd); - if (ret < 0) return CL_EREAD; - - nwatches = strtol(nwatch_str, &p, 10); - - ret = onas_ddd_init_wdlt(nwatches); - if (ret) return ret; - - ret = onas_ddd_init_ht(ht_size); - if (ret) return ret; - - return CL_SUCCESS; -} - -static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask) { - if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG; - - int ret = CL_SUCCESS; - size_t len = strlen(pathname); - - ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN); - if (ret) return ret; - - ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN); - if (ret) return ret; - - return CL_SUCCESS; -} - -static int onas_ddd_watch_hierarchy(const char* pathname, size_t len, int fd, uint64_t mask, uint32_t type) { - - if (!pathname || fd <= 0 || !type) return CL_ENULLARG; - - if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG; - - struct onas_hnode *hnode = NULL; - struct onas_element *elem = NULL; - int wd = 0; - - if(onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG; - - hnode = elem->data; - - if (type & ONAS_IN) { - wd = inotify_add_watch(fd, pathname, (uint32_t) mask); - - if (wd < 0) return CL_EARG; - - if ((uint32_t) wd >= wdlt_len) { - onas_ddd_grow_wdlt(); - } - - /* Link the hash node to the watch descriptor lookup table */ - hnode->wd = wd; - wdlt[wd] = hnode->pathname; - - hnode->watched |= ONAS_INWATCH; - } else if (type & ONAS_FAN) { - if(fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG; - hnode->watched |= ONAS_FANWATCH; - } else { - return CL_EARG; - } - - struct onas_lnode *curr = hnode->childhead; - - while (curr->next != hnode->childtail) { - curr = curr->next; - - size_t size = len + strlen(curr->dirname) + 2; - char *child_path = (char *) cli_malloc(size); - if (child_path == NULL) - return CL_EMEM; - if (hnode->pathname[len-1] == '/') - snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname); - else - snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); - - if(onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) { - return CL_EARG; - } - free(child_path); - } - - return CL_SUCCESS; -} - -static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd) { - if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG; - - int ret = CL_SUCCESS; - size_t len = strlen(pathname); - - ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN); - if (ret) return ret; - - ret = onas_ddd_unwatch_hierarchy(pathname, len,fan_fd, ONAS_FAN); - if (ret) return ret; - - return CL_SUCCESS; -} - -static int onas_ddd_unwatch_hierarchy(const char* pathname, size_t len, int fd, uint32_t type) { - - if (!pathname || fd <= 0 || !type) return CL_ENULLARG; - - if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG; - - struct onas_hnode *hnode = NULL; - struct onas_element *elem = NULL; - int wd = 0; - - if(onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG; - - hnode = elem->data; - - if (type & ONAS_IN) { - wd = hnode->wd; - - if(!inotify_rm_watch(fd, wd)) return CL_EARG; - - /* Unlink the hash node from the watch descriptor lookup table */ - hnode->wd = 0; - wdlt[wd] = NULL; - - hnode->watched = ONAS_STOPWATCH; - } else if (type & ONAS_FAN) { - if(fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG; - hnode->watched = ONAS_STOPWATCH; - } else { - return CL_EARG; - } - - struct onas_lnode *curr = hnode->childhead; - - while (curr->next != hnode->childtail) { - curr = curr->next; - - size_t size = len + strlen(curr->dirname) + 2; - char *child_path = (char *) cli_malloc(size); - if (child_path == NULL) - return CL_EMEM; - if (hnode->pathname[len-1] == '/') - snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname); - else - snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); - - onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type); - free(child_path); - } - - return CL_SUCCESS; -} - -void *onas_ddd_th(void *arg) { - struct ddd_thrarg *tharg = (struct ddd_thrarg *) arg; - sigset_t sigset; - struct sigaction act; - const struct optstruct *pt; - uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; - fd_set rfds; - char buf[4096]; - ssize_t bread; - const struct inotify_event *event; - int ret, len; - - /* ignore all signals except SIGUSR1 */ - sigfillset(&sigset); - sigdelset(&sigset, SIGUSR1); - /* The behavior of a process is undefined after it ignores a - * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ - sigdelset(&sigset, SIGFPE); - sigdelset(&sigset, SIGILL); - sigdelset(&sigset, SIGSEGV); -#ifdef SIGBUS - sigdelset(&sigset, SIGBUS); -#endif - pthread_sigmask(SIG_SETMASK, &sigset, NULL); - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = onas_ddd_exit; - sigfillset(&(act.sa_mask)); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGSEGV, &act, NULL); - - onas_in_fd = inotify_init1(IN_NONBLOCK); - if (onas_in_fd == -1) { - logg("!ScanOnAccess: Could not init inotify."); - return NULL; - } - - ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); - if (ret) { - logg("!ScanOnAccess: Failed to initialize 3D. \n"); - return NULL; - } - - /* Add provided paths recursively. */ - if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) { - while(pt) { - if (!strcmp(pt->strarg, "/")) { - logg("!ScanOnAccess: Not including path '%s' while DDD is enabled\n", pt->strarg); - logg("!ScanOnAccess: Please use the OnAccessMountPath option to watch '%s'\n", pt->strarg); - pt = (struct optstruct *) pt->nextarg; - continue; - } - if(onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { - if(onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { - logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg); - return NULL; - } else - logg("ScanOnAccess: Protecting directory '%s' (and all sub-directories)\n", pt->strarg); - } - - pt = (struct optstruct *) pt->nextarg; - } - } else { - logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n"); - return NULL; - } - - /* Remove provided paths recursively. */ - if((pt = optget(tharg->opts, "OnAccessExcludePath"))->enabled) { - while(pt) { - size_t ptlen = strlen(pt->strarg); - if(onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { - if(onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { - logg("!ScanOnAccess: Can't exclude path '%s'\n", pt->strarg); - return NULL; - } else - logg("ScanOnAccess: Excluding directory '%s' (and all sub-directories)\n", pt->strarg); - } - - pt = (struct optstruct *) pt->nextarg; - } - } - - /* Watch provided paths recursively */ - if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) { - while(pt) { - size_t ptlen = strlen(pt->strarg); - if(onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { - if(onas_ddd_watch(pt->strarg, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask)) { - logg("!ScanOnAccess: Could not watch path '%s', %s\n", pt->strarg, strerror(errno)); - if(errno == EINVAL && optget(tharg->opts, "OnAccessPrevention")->enabled) { - logg("!ScanOnAccess: When using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); - - kill(getpid(), SIGTERM); - } - return NULL; - } - } - pt = (struct optstruct *) pt->nextarg; - } - } - - /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */ -#if 0 - if(optget(tharg->opts, "OnAccessExtraScanning")->enabled) { - logg("ScanOnAccess: Extra scanning and notifications enabled.\n"); -} - #endif - - - FD_ZERO(&rfds); - FD_SET(onas_in_fd, &rfds); - - while (1) { - do { - ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); - } while(ret == -1 && errno == EINTR); - - while((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { - - /* Handle events. */ - int wd; - char *p = buf; - const char *path = NULL; - const char *child = NULL; - for(; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { - - event = (const struct inotify_event *) p; - wd = event->wd; - path = wdlt[wd]; - child = event->name; - - len = strlen(path); - size_t size = strlen(child) + len + 2; - char *child_path = (char *) cli_malloc(size); - if (child_path == NULL) - return NULL; - - if (path[len-1] == '/') - snprintf(child_path, --size, "%s%s", path, child); - else - snprintf(child_path, size, "%s/%s", path, child); - - if (event->mask & IN_DELETE) { - onas_ddd_handle_in_delete(tharg, path, child_path, event, wd); - - } else if (event->mask & IN_MOVED_FROM) { - onas_ddd_handle_in_moved_from(tharg, path, child_path, event, wd); - - } else if (event->mask & IN_CREATE) { - onas_ddd_handle_in_create(tharg, path, child_path, event, wd, in_mask); - - } else if (event->mask & IN_MOVED_TO) { - onas_ddd_handle_in_moved_to(tharg, path, child_path, event, wd, in_mask); - } - } - } - } - - return NULL; -} - -static void onas_ddd_handle_in_delete(struct ddd_thrarg *tharg, - const char *path, const char *child_path, const struct inotify_event *event, int wd) { - - struct stat s; - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; - if(!(event->mask & IN_ISDIR)) return; - - logg("*ddd: DELETE - Removing %s from %s with wd:%d\n", child_path, path, wd); - onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd); - onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); - - return; -} - - -static void onas_ddd_handle_in_moved_from(struct ddd_thrarg *tharg, - const char *path, const char *child_path, const struct inotify_event *event, int wd) { - - struct stat s; - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; - if(!(event->mask & IN_ISDIR)) return; - - logg("*ddd: MOVED_FROM - Removing %s from %s with wd:%d\n", child_path, path, wd); - onas_ddd_unwatch(child_path, tharg->fan_fd, onas_in_fd); - onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); - - return; -} - - -static void onas_ddd_handle_in_create(struct ddd_thrarg *tharg, - const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) { - - struct stat s; - - /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */ -#if 0 - if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) { - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { - onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE); - - } else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) { - logg("*ddd: CREATE - Adding %s to %s with wd:%d\n", child_path, path, wd); - onas_ht_add_hierarchy(ddd_ht, child_path); - onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask); - - onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR); - } - } - else -#endif - { - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; - if(!(event->mask & IN_ISDIR)) return; - - logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd); - onas_ht_add_hierarchy(ddd_ht, child_path); - onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask); - } - - return; -} - -static void onas_ddd_handle_in_moved_to(struct ddd_thrarg *tharg, - const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) { - - struct stat s; - /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */ -#if 0 - if (optget(tharg->opts, "OnAccessExtraScanning")->enabled) { - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { - onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISFILE); - - } else if(stat(child_path, &s) == 0 && S_ISDIR(s.st_mode)) { - logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd); - onas_ht_add_hierarchy(ddd_ht, child_path); - onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask); - - onas_ddd_handle_extra_scanning(tharg, child_path, ONAS_SCTH_ISDIR); - } - } - else -#endif - { - if(stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; - if(!(event->mask & IN_ISDIR)) return; - - logg("*ddd: MOVED_TO - Adding %s to %s with wd:%d\n", child_path, path, wd); - onas_ht_add_hierarchy(ddd_ht, child_path); - onas_ddd_watch(child_path, tharg->fan_fd, tharg->fan_mask, onas_in_fd, in_mask); - } - - return; -} - -static void onas_ddd_handle_extra_scanning(struct ddd_thrarg *tharg, const char *pathname, int extra_options) { - - int thread_started = 1; - struct scth_thrarg *scth_tharg = NULL; - pthread_attr_t scth_attr; - pthread_t scth_pid = 0; - - do { - if (pthread_attr_init(&scth_attr)) break; - pthread_attr_setdetachstate(&scth_attr, PTHREAD_CREATE_JOINABLE); - - /* Allocate memory for arguments. Thread is responsible for freeing it. */ - if (!(scth_tharg = (struct scth_thrarg *) calloc(sizeof(struct scth_thrarg), 1))) break; - if (!(scth_tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break; - - (void) memcpy(scth_tharg->options, tharg->options, sizeof(struct cl_scan_options)); - - scth_tharg->extra_options = extra_options; - scth_tharg->opts = tharg->opts; - scth_tharg->pathname = strdup(pathname); - scth_tharg->engine = tharg->engine; - - thread_started = pthread_create(&scth_pid, &scth_attr, onas_scan_th, scth_tharg); - } while(0); - - if (0 != thread_started) { - /* Failed to create thread. Free anything we may have allocated. */ - logg("!ScanOnAccess: Unable to kick off extra scanning.\n"); - if (NULL != scth_tharg) { - if (NULL != scth_tharg->pathname){ - free(scth_tharg->pathname); - scth_tharg->pathname = NULL; - } - if (NULL != scth_tharg->options) { - free(scth_tharg->options); - scth_tharg->options = NULL; - } - free(scth_tharg); - scth_tharg = NULL; - } - } - - return; -} - - -static void onas_ddd_exit(int sig) { - logg("*ScanOnAccess: onas_ddd_exit(), signal %d\n", sig); - - close(onas_in_fd); - - onas_free_ht(ddd_ht); - free(wdlt); - - pthread_exit(NULL); - logg("ScanOnAccess: stopped\n"); -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_ddd.h clamav-0.102.1+dfsg/clamd/onaccess_ddd.h --- clamav-0.101.4+dfsg/clamd/onaccess_ddd.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_ddd.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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. - */ - -#ifndef __ONAS_IN_H -#define __ONAS_IN_H - -#include "shared/optparser.h" -#include "libclamav/clamav.h" - -/* - * Extra options for onas_scan_th(). - */ -#define ONAS_IN 0x01 -#define ONAS_FAN 0x02 - -#define MAX_WATCH_LEN 7 - -struct ddd_thrarg { - int sid; - struct cl_scan_options *options; - int fan_fd; - uint64_t fan_mask; - const struct optstruct *opts; - const struct cl_engine *engine; -}; - - -int onas_ddd_init(uint64_t nwatches, size_t ht_size); -void *onas_ddd_th(void *arg); - - -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_fan.c clamav-0.102.1+dfsg/clamd/onaccess_fan.c --- clamav-0.101.4+dfsg/clamd/onaccess_fan.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_fan.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * Copyright (C) 2011-2013 Sourcefire, Inc. - * - * Authors: Tomasz Kojm, Mickey Sola - * - * 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 - -#if defined(FANOTIFY) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "libclamav/clamav.h" -#include "libclamav/scanners.h" - -#include "shared/optparser.h" -#include "shared/output.h" - -#include "onaccess_others.h" -#include "server.h" - -#include "onaccess_fan.h" -#include "onaccess_hash.h" -#include "onaccess_ddd.h" - -static pthread_t ddd_pid; -static int onas_fan_fd; - -static void onas_fan_exit(int sig) -{ - logg("*ScanOnAccess: onas_fan_exit(), signal %d\n", sig); - - close(onas_fan_fd); - - if (ddd_pid > 0) { - pthread_kill(ddd_pid, SIGUSR1); - pthread_join(ddd_pid, NULL); - } - - pthread_exit(NULL); - logg("ScanOnAccess: stopped\n"); -} - -static int onas_fan_scanfile(int fan_fd, const char *fname, struct fanotify_event_metadata *fmd, int scan, int extinfo, struct thrarg *tharg) -{ - struct fanotify_response res; - const char *virname = NULL; - int ret = 0; - - res.fd = fmd->fd; - res.response = FAN_ALLOW; - - if (scan) { - if (onas_scan(fname, fmd->fd, &virname, tharg->engine, tharg->options, extinfo) == CL_VIRUS) { - /* TODO : FIXME? virusaction forks. This could be extraordinarily problematic, lead to deadlocks, - * or at the very least lead to extreme memory consumption. Leaving disabled for now.*/ - //virusaction(fname, virname, tharg->opts); - res.response = FAN_DENY; - } - } - - if(fmd->mask & FAN_ALL_PERM_EVENTS) { - ret = write(fan_fd, &res, sizeof(res)); - if(ret == -1) - logg("!ScanOnAccess: Internal error (can't write to fanotify)\n"); - } - - return ret; -} - -void *onas_fan_th(void *arg) -{ - struct thrarg *tharg = (struct thrarg *) arg; - sigset_t sigset; - struct sigaction act; - const struct optstruct *pt; - short int scan; - unsigned int sizelimit = 0, extinfo; - STATBUF sb; - uint64_t fan_mask = FAN_EVENT_ON_CHILD | FAN_CLOSE; - fd_set rfds; - char buf[4096]; - ssize_t bread; - struct fanotify_event_metadata *fmd; - char fname[1024]; - int ret, len, check; - char err[128]; - - pthread_attr_t ddd_attr; - struct ddd_thrarg *ddd_tharg = NULL; - - ddd_pid = 0; - - /* ignore all signals except SIGUSR1 */ - sigfillset(&sigset); - sigdelset(&sigset, SIGUSR1); - /* The behavior of a process is undefined after it ignores a - * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ - sigdelset(&sigset, SIGFPE); - sigdelset(&sigset, SIGILL); - sigdelset(&sigset, SIGSEGV); -#ifdef SIGBUS - sigdelset(&sigset, SIGBUS); -#endif - pthread_sigmask(SIG_SETMASK, &sigset, NULL); - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = onas_fan_exit; - sigfillset(&(act.sa_mask)); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGSEGV, &act, NULL); - - /* Initialize fanotify */ - onas_fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); - if(onas_fan_fd < 0) { - logg("!ScanOnAccess: fanotify_init failed: %s\n", cli_strerror(errno, err, sizeof(err))); - if(errno == EPERM) - logg("ScanOnAccess: clamd must be started by root\n"); - return NULL; - } - - if (!tharg) { - logg("!Unable to start on-access scanner. Bad thread args.\n"); - return NULL; - } - - - if (optget(tharg->opts, "OnAccessPrevention")->enabled && !optget(tharg->opts, "OnAccessMountPath")->enabled) { - logg("ScanOnAccess: preventing access attempts on malicious files.\n"); - fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM; - } else { - logg("ScanOnAccess: notifying only for access attempts.\n"); - fan_mask |= FAN_ACCESS | FAN_OPEN; - } - - if ((pt = optget(tharg->opts, "OnAccessMountPath"))->enabled) { - while(pt) { - if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, fan_mask, onas_fan_fd, pt->strarg) != 0) { - logg("!ScanOnAccess: Can't include mountpoint '%s'\n", pt->strarg); - return NULL; - } else - logg("ScanOnAccess: Protecting '%s' and rest of mount.\n", pt->strarg); - pt = (struct optstruct *) pt->nextarg; - } - - } else if (!optget(tharg->opts, "OnAccessDisableDDD")->enabled) { - int thread_started = 1; - do { - if(pthread_attr_init(&ddd_attr)) break; - pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE); - - /* Allocate memory for arguments. Thread is responsible for freeing it. */ - if (!(ddd_tharg = (struct ddd_thrarg *) calloc(sizeof(struct ddd_thrarg), 1))) break; - if (!(ddd_tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break; - - (void) memcpy(ddd_tharg->options, tharg->options, sizeof(struct cl_scan_options)); - ddd_tharg->fan_fd = onas_fan_fd; - ddd_tharg->fan_mask = fan_mask; - ddd_tharg->opts = tharg->opts; - ddd_tharg->engine = tharg->engine; - - thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, ddd_tharg); - } while(0); - - if (0 != thread_started) { - /* Failed to create thread. Free anything we may have allocated. */ - logg("!Unable to start dynamic directory determination.\n"); - if (NULL != ddd_tharg) { - if (NULL != ddd_tharg->options) { - free(ddd_tharg->options); - ddd_tharg->options = NULL; - } - free(ddd_tharg); - ddd_tharg = NULL; - } - } - - } else { - if((pt = optget(tharg->opts, "OnAccessIncludePath"))->enabled) { - while(pt) { - if(fanotify_mark(onas_fan_fd, FAN_MARK_ADD, fan_mask, onas_fan_fd, pt->strarg) != 0) { - logg("!ScanOnAccess: Can't include path '%s'\n", pt->strarg); - return NULL; - } else - logg("ScanOnAccess: Protecting directory '%s'\n", pt->strarg); - pt = (struct optstruct *) pt->nextarg; - } - } else { - logg("!ScanOnAccess: Please specify at least one path with OnAccessIncludePath\n"); - return NULL; - } - } - - /* Load other options. */ - sizelimit = optget(tharg->opts, "OnAccessMaxFileSize")->numarg; - if(sizelimit) - logg("ScanOnAccess: Max file size limited to %u bytes\n", sizelimit); - else - logg("ScanOnAccess: File size limit disabled\n"); - - extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; - - FD_ZERO(&rfds); - FD_SET(onas_fan_fd, &rfds); - do { - if (reload) sleep(1); - ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL); - } while((ret == -1 && errno == EINTR) || reload); - - - time_t start = time(NULL) - 30; - while(((bread = read(onas_fan_fd, buf, sizeof(buf))) > 0) || errno == EOVERFLOW) { - - if (errno == EOVERFLOW) { - if (time(NULL) - start >= 30) { - logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno)); - logg("!ScanOnAccess: File too large for fanotify ... recovering and continuing scans...\n"); - start = time(NULL); - } - - errno = 0; - continue; - } - - fmd = (struct fanotify_event_metadata *) buf; - while(FAN_EVENT_OK(fmd, bread)) { - scan = 1; - if(fmd->fd >= 0) { - sprintf(fname, "/proc/self/fd/%d", fmd->fd); - len = readlink(fname, fname, sizeof(fname) - 1); - if(len == -1) { - close(fmd->fd); - logg("!ScanOnAccess: Internal error (readlink() failed)\n"); - return NULL; - } - fname[len] = 0; - - if((check = onas_fan_checkowner(fmd->pid, tharg->opts))) { - scan = 0; - /* TODO: Re-enable OnAccessExtraScanning once the thread resource consumption issue is resolved. */ - #if 0 - if ((check != CHK_SELF) || !(optget(tharg->opts, "OnAccessExtraScanning")->enabled)) { - #else - if (check != CHK_SELF) { - #endif - logg("*ScanOnAccess: %s skipped (excluded UID)\n", fname); - } - } - - if(sizelimit) { - if(FSTAT(fmd->fd, &sb) != 0 || sb.st_size > sizelimit) { - scan = 0; - /* logg("*ScanOnAccess: %s skipped (size > %d)\n", fname, sizelimit); */ - } - } - - if(onas_fan_scanfile(onas_fan_fd, fname, fmd, scan, extinfo, tharg) == -1) { - close(fmd->fd); - return NULL; - } - - if(close(fmd->fd) == -1) { - printf("!ScanOnAccess: Internal error (close(%d) failed)\n", fmd->fd); - close(fmd->fd); - return NULL; - } - } - fmd = FAN_EVENT_NEXT(fmd, bread); - } - do { - if (reload) sleep(1); - ret = select(onas_fan_fd + 1, &rfds, NULL, NULL, NULL); - } while((ret == -1 && errno == EINTR) || reload); - } - - if(bread < 0) - logg("!ScanOnAccess: Internal error (failed to read data) ... %s\n", strerror(errno)); - - return NULL; -} - - -/* CLAMAUTH is deprecated */ -#elif defined(CLAMAUTH) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libclamav/clamav.h" -#include "libclamav/scanners.h" - -#include "shared/optparser.h" -#include "shared/output.h" - -#include "server.h" -#include "others.h" -#include "scanner.h" - -#define SUPPORTED_PROTOCOL 2 - -static int cauth_fd = -1; - -struct ClamAuthEvent { - unsigned int action; - char path[1024]; - unsigned int pid; -}; - -static void cauth_exit(int sig) -{ - logg("*ScanOnAccess: cauth_exit(), signal %d\n", sig); - if(cauth_fd > 0) - close(cauth_fd); - pthread_exit(NULL); - logg("ScanOnAccess: stopped\n"); -} - -static int cauth_scanfile(const char *fname, int extinfo, struct thrarg *tharg) -{ - struct cb_context context; - const char *virname = NULL; - int ret = 0, fd; - - context.filename = fname; - context.virsize = 0; - context.scandata = NULL; - - fd = open(fname, O_RDONLY); - if(fd == -1) - return -1; - - if(cl_scandesc_callback(fd, fname, &virname, NULL, tharg->engine, tharg->options, &context) == CL_VIRUS) { - if(extinfo && context.virsize) - logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, virname, context.virhash, context.virsize); - else - logg("ScanOnAccess: %s: %s FOUND\n", fname, virname); - virusaction(fname, virname, tharg->opts); - } - close(fd); - return ret; -} - -void *onas_fan_th(void *arg) -{ - struct thrarg *tharg = (struct thrarg *) arg; - sigset_t sigset; - struct sigaction act; - int eventcnt = 1, extinfo; - char err[128]; - struct ClamAuthEvent event; - - /* ignore all signals except SIGUSR1 */ - sigfillset(&sigset); - sigdelset(&sigset, SIGUSR1); - /* The behavior of a process is undefined after it ignores a - * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ - sigdelset(&sigset, SIGFPE); - sigdelset(&sigset, SIGILL); - sigdelset(&sigset, SIGSEGV); -#ifdef SIGBUS - sigdelset(&sigset, SIGBUS); -#endif - pthread_sigmask(SIG_SETMASK, &sigset, NULL); - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = cauth_exit; - sigfillset(&(act.sa_mask)); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGSEGV, &act, NULL); - - extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; - - cauth_fd = open("/dev/clamauth", O_RDONLY); - if(cauth_fd == -1) { - logg("!ScanOnAccess: Can't open /dev/clamauth\n"); - if(errno == ENOENT) - logg("!ScanOnAccess: Please make sure ClamAuth.kext is loaded\n"); - else if(errno == EACCES) - logg("!ScanOnAccess: This application requires root privileges\n"); - else - logg("!ScanOnAccess: /dev/clamauth: %s\n", cli_strerror(errno, err, sizeof(err))); - - return NULL; - } - - while(1) { - if(read(cauth_fd, &event, sizeof(event)) > 0) { - if(eventcnt == 1) { - if(event.action != SUPPORTED_PROTOCOL) { - logg("!ScanOnAccess: Protocol version mismatch (tool: %d, driver: %d)\n", SUPPORTED_PROTOCOL, event.action); - close(cauth_fd); - return NULL; - } - if(strncmp(event.path, "ClamAuth", 8)) { - logg("!ScanOnAccess: Invalid version event\n"); - close(cauth_fd); - return NULL; - } - logg("ScanOnAccess: Driver version: %s, protocol version: %d\n", &event.path[9], event.action); - } else { - cauth_scanfile(event.path, extinfo, tharg); - } - eventcnt++; - } else { - if(errno == ENODEV) { - printf("^ScanOnAccess: ClamAuth module deactivated, terminating\n"); - close(cauth_fd); - return NULL; - } - } - usleep(200); - } -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_fan.h clamav-0.102.1+dfsg/clamd/onaccess_fan.h --- clamav-0.101.4+dfsg/clamd/onaccess_fan.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_fan.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * Copyright (C) 2011-2013 Sourcefire, Inc. - * - * Authors: Tomasz Kojm - * - * 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. - */ - -#ifndef __FAN_H -#define __FAN_H - -void *onas_fan_th(void *arg); - -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_hash.c clamav-0.102.1+dfsg/clamd/onaccess_hash.c --- clamav-0.101.4+dfsg/clamd/onaccess_hash.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_hash.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,675 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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 - -#if defined(FANOTIFY) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "onaccess_fan.h" -#include "onaccess_hash.h" -#include "onaccess_ddd.h" - -#include "libclamav/clamav.h" -#include "libclamav/scanners.h" -#include "libclamav/str.h" - -#include "shared/optparser.h" -#include "shared/output.h" - -#include "server.h" -#include "others.h" -#include "scanner.h" -#include "priv_fts.h" - -static struct onas_bucket *onas_bucket_init(); -static void onas_free_bucket(struct onas_bucket *bckt); -static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem); -static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem); - -static int onas_add_hashnode_child(struct onas_hnode *node, const char* dirname); - -static struct onas_lnode *onas_listnode_init(void); - -static struct onas_hnode *onas_hashnode_init(void); - -static inline uint32_t onas_hshift(uint32_t hash) { - - hash = ~hash; - - hash += (hash << 15); - hash ^= (hash >> 12); - hash += (hash << 2); - hash ^= (hash >> 4); - hash += (hash << 3); - hash += (hash << 11); - hash ^= (hash >> 16); - - return hash; -} - -static inline int onas_hash(const char* key, size_t keylen, uint32_t size) { - - uint32_t hash = 1; - uint32_t i; - - for (i = 0; i < keylen; i++) { - hash += key[i]; - hash = onas_hshift(hash); - } - - return hash & (size - 1); -} - -int onas_ht_init(struct onas_ht **ht, uint32_t size) { - - if (size == 0 || (size & (~size + 1)) != size) return CL_EARG; - - *ht = (struct onas_ht *) cli_malloc(sizeof(struct onas_ht)); - if (!(*ht)) return CL_EMEM; - - **ht = (struct onas_ht) { - .htable = NULL, - .size = size, - .nbckts = 0, - }; - - if (!((*ht)->htable = (struct onas_bucket **) cli_calloc(size, sizeof(struct onas_bucket *)))) { - onas_free_ht(*ht); - return CL_EMEM; - } - - return CL_SUCCESS; -} - -void onas_free_ht(struct onas_ht *ht) { - - if (!ht || ht->size == 0) return; - - if (!ht->htable) { - free(ht); - return; - } - - uint32_t i = 0; - for (i = 0; i < ht->size; i++) { - onas_free_bucket(ht->htable[i]); - ht->htable[i] = NULL; - } - - free(ht->htable); - ht->htable = NULL; - - free(ht); - - return; -} - -static struct onas_bucket *onas_bucket_init() { - - struct onas_bucket *bckt = (struct onas_bucket*) cli_malloc(sizeof(struct onas_bucket)); - if (!bckt) return NULL; - - *bckt = (struct onas_bucket) { - .size = 0, - .head = NULL, - .tail = NULL - }; - - return bckt; -} - -static void onas_free_bucket(struct onas_bucket *bckt) { - - if (!bckt) return; - - uint32_t i = 0; - struct onas_element *curr = NULL; - - for (i = 0; i < bckt->size; i++) { - curr = bckt->head; - bckt->head = curr->next; - onas_free_element(curr); - curr = NULL; - } - - free(bckt); - - return; -} - -struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen) { - - struct onas_element *elem = (struct onas_element *) cli_malloc(sizeof(struct onas_element)); - if (!elem) return NULL; - - *elem = (struct onas_element) { - .key = key, - .klen = klen, - .data = value, - .next = NULL, - .prev = NULL - }; - - return elem; -} - -void onas_free_element(struct onas_element *elem) { - - if (!elem) return; - - onas_free_hashnode(elem->data); - - elem->prev = NULL; - elem->next = NULL; - - free(elem); - - return; -} - -int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem) { - - if (!ht || !elem || !elem->key) return CL_ENULLARG; - - int idx = onas_hash(elem->key, elem->klen, ht->size); - struct onas_bucket *bckt = ht->htable[idx]; - - int ret = 0; - uint32_t bsize = 0; - - if (bckt == NULL) { - ht->htable[idx] = onas_bucket_init(); - bckt = ht->htable[idx]; - } - - bsize = bckt->size; - ret = onas_bucket_insert(bckt, elem); - - if (ret == CL_SUCCESS) - if (bsize < bckt->size) - ht->nbckts++; - - return ret; -} - -static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem) { - if (!bckt || !elem) return CL_ENULLARG; - - if (bckt->size == 0) { - bckt->head = elem; - bckt->tail = elem; - elem->prev = NULL; - elem->next = NULL; - bckt->size++; - } else { - struct onas_element *btail = bckt->tail; - - btail->next = elem; - elem->prev = btail; - elem->next = NULL; - bckt->tail = elem; - bckt->size++; - } - - return CL_SUCCESS; -} - -/* Checks if key exists and optionally stores address to the element corresponding to the key within elem */ -int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem) { - - if (elem) *elem = NULL; - - if (!ht || !key || klen <= 0) return CL_ENULLARG; - - struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)]; - - if (!bckt || bckt->size == 0) return CL_EARG; - - struct onas_element *curr = bckt->head; - - while (curr && strcmp(curr->key, key)) { - curr = curr->next; - } - - if (!curr) return CL_EARG; - - if (elem) *elem = curr; - - return CL_SUCCESS; -} - -/* Removes the element corresponding to key from the hashtable and optionally returns a pointer to the removed element. */ -int onas_ht_remove(struct onas_ht *ht, const char* key, size_t klen, struct onas_element **relem) { - if (!ht || !key || klen <= 0) return CL_ENULLARG; - - struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)]; - - if (!bckt) return CL_EARG; - - struct onas_element *elem = NULL; - onas_ht_get(ht, key, klen, &elem); - - if (!elem) return CL_EARG; - - int ret = onas_bucket_remove(bckt, elem); - - if (relem) *relem = elem; - - return ret; -} - -static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem) { - if (!bckt || !elem) return CL_ENULLARG; - - struct onas_element *curr = bckt->head; - - while (curr && curr != elem) { - curr = curr->next; - } - - if (!curr) return CL_EARG; - - if (bckt->head == elem) { - bckt->head = elem->next; - if (bckt->head) bckt->head->prev = NULL; - - elem->next = NULL; - } else if (bckt->tail == elem) { - bckt->tail = elem->prev; - if (bckt->tail) bckt->tail->next = NULL; - - elem->prev = NULL; - } else { - struct onas_element *tmp = NULL; - - tmp = elem->prev; - if (tmp) { - tmp->next = elem->next; - tmp = elem->next; - tmp->prev = elem->prev; - } - - elem->prev = NULL; - elem->next = NULL; - } - - bckt->size--; - - return CL_SUCCESS; -} - - -/* Dealing with hash nodes and list nodes */ - -/* Function to initialize hashnode. */ -static struct onas_hnode *onas_hashnode_init(void) { - struct onas_hnode *hnode = NULL; - if(!(hnode = (struct onas_hnode *) cli_malloc(sizeof(struct onas_hnode)))) { - return NULL; - } - - *hnode = (struct onas_hnode) { - .pathlen = 0, - .pathname = NULL, - .prnt_pathlen = 0, - .prnt_pathname = NULL, - .childhead = NULL, - .childtail = NULL, - .wd = 0, - .watched = 0 - }; - - if (!(hnode->childhead = (struct onas_lnode *) onas_listnode_init())) { - onas_free_hashnode(hnode); - return NULL; - } - - if (!(hnode->childtail = (struct onas_lnode *) onas_listnode_init())) { - onas_free_hashnode(hnode); - return NULL; - } - - hnode->childhead->next = (struct onas_lnode *) hnode->childtail; - hnode->childtail->prev = (struct onas_lnode *) hnode->childhead; - - return hnode; -} - -/* Function to initialize listnode. */ -static struct onas_lnode *onas_listnode_init(void) { - struct onas_lnode *lnode = NULL; - if(!(lnode = (struct onas_lnode *) cli_malloc(sizeof(struct onas_lnode)))) { - return NULL; - } - - *lnode = (struct onas_lnode) { - .dirname = NULL, - .next = NULL, - .prev = NULL - }; - - return lnode; -} - -/* Function to free hashnode. */ -void onas_free_hashnode(struct onas_hnode *hnode) { - if (!hnode) return; - - onas_free_dirlist(hnode->childhead); - hnode->childhead = NULL; - - free(hnode->pathname); - hnode->pathname = NULL; - - free(hnode->prnt_pathname); - hnode->prnt_pathname = NULL; - - free(hnode); - - return; -} - - -/* Function to free list of listnodes. */ -void onas_free_dirlist(struct onas_lnode *head) { - if (!head) return; - struct onas_lnode *curr = head; - struct onas_lnode *tmp = curr; - - while(curr) { - tmp = curr->next; - onas_free_listnode(curr); - curr = tmp; - } - - return; -} - -/* Function to free a listnode. */ -void onas_free_listnode(struct onas_lnode *lnode) { - if (!lnode) return; - - lnode->next = NULL; - lnode->prev = NULL; - - free(lnode->dirname); - lnode->dirname = NULL; - - free(lnode); - - return; -} - -static int onas_add_hashnode_child(struct onas_hnode *node, const char* dirname) { - if (!node || !dirname) return CL_ENULLARG; - - struct onas_lnode *child = onas_listnode_init(); - if (!child) return CL_EMEM; - - size_t n = strlen(dirname); - child->dirname = cli_strndup(dirname, n); - - onas_add_listnode(node->childtail, child); - - return CL_SUCCESS; -} - -/* Function to add a dir_listnode to a list */ -int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node) { - if (!tail || !node) return CL_ENULLARG; - - struct onas_lnode *tmp = tail->prev; - - tmp->next = node; - node->prev = tail->prev; - - node->next = tail; - tail->prev = node; - - return CL_SUCCESS; -} - -/* Function to remove a listnode based on dirname. */ -int onas_rm_listnode(struct onas_lnode *head, const char *dirname) { - if (!dirname || !head) return CL_ENULLARG; - - struct onas_lnode *curr = head; - size_t n = strlen(dirname); - - while ((curr = curr->next)) { - if (!strncmp(curr->dirname, dirname, n)) { - struct onas_lnode *tmp = curr->prev; - tmp->next = curr->next; - tmp = curr->next; - tmp->prev = curr->prev; - - onas_free_listnode(curr); - - return CL_SUCCESS; - } - } - - return -1; -} - -/*** Dealing with parent/child relationships in the table. ***/ - -/* Determines parent and returns a copy based on full pathname. */ -inline static char *onas_get_parent(const char *pathname, size_t len) { - if (!pathname || len <= 1) return NULL; - - int idx = len - 2; - char *ret = NULL; - - while(idx >= 0 && pathname[idx] != '/') { - idx--; - } - - if (idx == 0) { - idx++; - } - - ret = cli_strndup(pathname, idx); - if (!ret) { - errno = ENOMEM; - return NULL; - } - - return ret; -} - -/* Gets the index at which the name of directory begins from the full pathname. */ -inline static int onas_get_dirname_idx(const char *pathname, size_t len) { - if (!pathname || len <= 1) return -1; - - int idx = len - 2; - - while(idx >= 0 && pathname[idx] != '/') { - idx--; - } - - if (pathname[idx] == '/') - return idx + 1; - - return idx; -} - -/* Emancipates the specified child from the specified parent. */ -int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen) { - - if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG; - - struct onas_element *elem = NULL; - struct onas_hnode *hnode = NULL; - int idx = onas_get_dirname_idx(childpath, childlen); - int ret = 0; - - if(idx <= 0) return CL_SUCCESS; - - if(onas_ht_get(ht, prntpath, prntlen, &elem) != CL_SUCCESS) return CL_EARG; - - hnode = elem->data; - - if ((ret = onas_rm_listnode(hnode->childhead, &(childpath[idx])))) return CL_EARG; - - return CL_SUCCESS; -} - -/* The specified parent adds the specified child to its list. */ -int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen) { - if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG; - - struct onas_element *elem = NULL; - struct onas_hnode *hnode = NULL; - int idx = onas_get_dirname_idx(childpath, childlen); - - if(idx <= 0) return CL_SUCCESS; - - if(onas_ht_get(ht, prntpath, prntlen, &elem)) return CL_EARG; - hnode = elem->data; - - return onas_add_hashnode_child(hnode, &(childpath[idx])); -} - -/*** Dealing with hierarchy changes. ***/ - -/* Adds the hierarchy under pathname to the tree and allocates all necessary memory. */ -int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname) { - - if (!ht || !pathname) return CL_ENULLARG; - - FTS *ftsp = NULL; - int ftspopts = FTS_PHYSICAL | FTS_XDEV; - FTSENT *curr = NULL; - FTSENT *childlist = NULL; - - size_t len = strlen(pathname); - char *prnt = onas_get_parent(pathname, len); - if (prnt) onas_ht_add_child(ht, prnt, strlen(prnt), pathname, len); - free(prnt); - - char * const pathargv[] = { (char*) pathname, NULL }; - if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { - logg("!ScanOnAccess: Could not open '%s'\n", pathname); - return CL_EARG; - } - - while((curr = _priv_fts_read(ftsp))) { - - struct onas_hnode *hnode = NULL; - - /* May want to handle other options in the future. */ - switch (curr->fts_info) { - case FTS_D: - hnode = onas_hashnode_init(); - if (!hnode) return CL_EMEM; - - hnode->pathlen = curr->fts_pathlen; - hnode->pathname = cli_strndup(curr->fts_path, hnode->pathlen); - - hnode->prnt_pathname = onas_get_parent(hnode->pathname, hnode->pathlen); - if (hnode->prnt_pathname) - hnode->prnt_pathlen = strlen(hnode->prnt_pathname); - else - hnode->prnt_pathlen = 0; - break; - default: - continue; - } - - if((childlist = _priv_fts_children(ftsp, 0))) { - do { - if (childlist->fts_info == FTS_D) { - if(CL_EMEM == onas_add_hashnode_child(hnode, childlist->fts_name)) - return CL_EMEM; - } - - } while ((childlist = childlist->fts_link)); - } - - struct onas_element *elem = onas_element_init(hnode, hnode->pathname, hnode->pathlen); - if (!elem) return CL_EMEM; - - if (onas_ht_insert(ht, elem)) return -1; - } - - _priv_fts_close(ftsp); - return CL_SUCCESS; -} - -/* Removes the underlying hierarchy from the tree and frees all associated memory. */ -int onas_ht_rm_hierarchy(struct onas_ht *ht, const char* pathname, size_t len, int level) { - if (!ht || !pathname || len <= 0) return CL_ENULLARG; - - struct onas_hnode *hnode = NULL; - struct onas_element *elem = NULL; - char *prntname = NULL; - size_t prntlen = 0; - - if(onas_ht_get(ht, pathname, len, &elem)) return CL_EARG; - - hnode = elem->data; - - struct onas_lnode *curr = hnode->childhead; - - if(level == 0) { - if(!(prntname = onas_get_parent(pathname, len))) return CL_EARG; - - prntlen = strlen(prntname); - if(onas_ht_rm_child(ht, prntname, prntlen, pathname, len)) return CL_EARG; - - free(prntname); - } - - while (curr->next != hnode->childtail) { - curr = curr->next; - - size_t size = len + strlen(curr->dirname) + 2; - char *child_path = (char *) cli_malloc(size); - if (child_path == NULL) - return CL_EMEM; - if (hnode->pathname[len-1] == '/') - snprintf(child_path, size, "%s%s", hnode->pathname, curr->dirname); - else - snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); - onas_ht_rm_hierarchy(ht, child_path, size, level + 1); - free(child_path); - } - - onas_ht_remove(ht, pathname, len, NULL); - onas_free_element(elem); - - return CL_SUCCESS; -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_hash.h clamav-0.102.1+dfsg/clamd/onaccess_hash.h --- clamav-0.101.4+dfsg/clamd/onaccess_hash.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_hash.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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. - */ - -#ifndef __ONAS_HASH_H -#define __ONAS_HASH_H - -#define ONAS_FANWATCH 0x1 -#define ONAS_INWATCH 0x2 -#define ONAS_STOPWATCH 0x3 - -#define ONAS_DEFAULT_HT_SIZE 1 << 18 - -struct onas_element { - - const char* key; - size_t klen; - struct onas_hnode *data; - - struct onas_element *next; - struct onas_element *prev; -}; - -struct onas_bucket { - - uint32_t size; - - struct onas_element *head; - struct onas_element *tail; -}; - -struct onas_ht { - - struct onas_bucket **htable; - - /* Must be a sufficiently high power of two--will not grow. */ - uint32_t size; - uint32_t nbckts; -}; - -/* Directory node struct for lists */ -struct onas_lnode { - - /* List stuffs */ - char *dirname; - struct onas_lnode *next; - struct onas_lnode *prev; -}; - -/* Directory node struct for hash tables */ -struct onas_hnode { - - /* Path info */ - int pathlen; - char *pathname; - - /* Parent info */ - int prnt_pathlen; - char *prnt_pathname; - - /* Child head and tail are empty sentinels */ - struct onas_lnode *childhead; - struct onas_lnode *childtail; - - /* Inotify watch descriptor */ - int wd; - - /* Watched stuffs */ - uint32_t watched; -}; - - -void onas_free_ht(struct onas_ht *ht); -int onas_ht_init(struct onas_ht **ht, uint32_t table_size); -int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem); -int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem); -int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem); -int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level); -int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname); -int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen); -int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen); - -void onas_free_element(struct onas_element *elem); -struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen); - -void onas_free_hashnode(struct onas_hnode *hnode); - -void onas_free_listnode(struct onas_lnode *lnode); -int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node); -int onas_rm_listnode(struct onas_lnode *head, const char *dirname); - -void onas_free_dirlist(struct onas_lnode *head); - -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_others.c clamav-0.102.1+dfsg/clamd/onaccess_others.c --- clamav-0.101.4+dfsg/clamd/onaccess_others.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_others.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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 - -#if defined(FANOTIFY) - -#include -#include -#include -#include -//#include -#include -#include -#include -//#include -#include "libclamav/clamav.h" -//#include "libclamav/scanners.h" -#include "shared/optparser.h" -#include "shared/output.h" -//#include "shared/misc.h" -//#include "libclamav/others.h" - -//#include "others.h" - -#include "onaccess_others.h" -#include "scanner.h" - -static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER; - -int onas_fan_checkowner(int pid, const struct optstruct *opts) -{ - char path[32]; - STATBUF sb; - const struct optstruct *opt = NULL; - const struct optstruct *opt_root = NULL; - - /* always ignore ourselves */ - if (pid == (int) getpid()) { - return CHK_SELF; - } - - /* look up options */ - opt = optget (opts, "OnAccessExcludeUID"); - opt_root = optget (opts, "OnAccessExcludeRootUID"); - - /* we can return immediately if no uid exclusions were requested */ - if (!(opt->enabled || opt_root->enabled)) - return CHK_CLEAN; - - /* perform exclusion checks if we can stat OK */ - snprintf (path, sizeof (path), "/proc/%u", pid); - if (CLAMSTAT (path, &sb) == 0) { - /* check all our non-root UIDs first */ - if (opt->enabled) { - while (opt) - { - if (opt->numarg == (long long) sb.st_uid) - return CHK_FOUND; - opt = opt->nextarg; - } - } - /* finally check root UID */ - if (opt_root->enabled) { - if (0 == (long long) sb.st_uid) - return CHK_FOUND; - } - } else if (errno == EACCES) { - logg("*Permission denied to stat /proc/%d to exclude UIDs... perhaps SELinux denial?\n", pid); - } else if (errno == ENOENT) { - /* FIXME: should this be configurable? */ - logg("$/proc/%d vanished before UIDs could be excluded; scanning anyway\n", pid); - } - - return CHK_CLEAN; -} - -int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo) -{ - int ret = 0; - struct cb_context context; - - pthread_mutex_lock(&onas_scan_lock); - - context.filename = fname; - context.virsize = 0; - context.scandata = NULL; - - ret = cl_scandesc_callback(fd, fname, virname, NULL, engine, options, &context); - - if (ret) { - if (extinfo && context.virsize) - logg("ScanOnAccess: %s: %s(%s:%llu) FOUND\n", fname, *virname, context.virhash, context.virsize); - else - logg("ScanOnAccess: %s: %s FOUND\n", fname, *virname); - } - - pthread_mutex_unlock(&onas_scan_lock); - - return ret; -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_others.h clamav-0.102.1+dfsg/clamd/onaccess_others.h --- clamav-0.101.4+dfsg/clamd/onaccess_others.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_others.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2017-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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. - */ - -#ifndef __CLAMD_ONAS_OTHERS_H -#define __CLAMD_ONAS_OTHERS_H - -#include "shared/optparser.h" -#include "libclamav/clamav.h" - -typedef enum { - CHK_CLEAN, - CHK_FOUND, - CHK_SELF -} cli_check_t; - -int onas_fan_checkowner(int pid, const struct optstruct *opts); -int onas_scan(const char *fname, int fd, const char **virname, const struct cl_engine *engine, struct cl_scan_options *options, int extinfo); - -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_scth.c clamav-0.102.1+dfsg/clamd/onaccess_scth.c --- clamav-0.101.4+dfsg/clamd/onaccess_scth.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_scth.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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 - -#if defined(FANOTIFY) - -#include -#include -#include -#include -#include -#include - -#include "shared/optparser.h" -#include "shared/output.h" - -#include "others.h" -#include "priv_fts.h" -#include "onaccess_others.h" -#include "onaccess_scth.h" -#include "onaccess_others.h" - -#include "libclamav/clamav.h" - - -static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg); -static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg); -static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg); - -static void onas_scth_exit(int sig); - -static void onas_scth_exit(int sig) { - logg("*ScanOnAccess: onas_scth_exit(), signal %d\n", sig); - - pthread_exit(NULL); -} - -static int onas_scth_scanfile(const char *fname, int fd, int extinfo, struct scth_thrarg *tharg) -{ - int ret = 0; - const char *virname = NULL; - - return onas_scan(fname, fd, &virname, tharg->engine, tharg->options, extinfo); -} - -static int onas_scth_handle_dir(const char *pathname, struct scth_thrarg *tharg) { - FTS *ftsp = NULL; - int fd; - int ftspopts = FTS_PHYSICAL | FTS_XDEV; - int extinfo; - int ret; - FTSENT *curr = NULL; - - extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; - - char *const pathargv[] = { (char *) pathname, NULL }; - if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) return CL_EOPEN; - - while ((curr = _priv_fts_read(ftsp))) { - if (curr->fts_info != FTS_D) { - if ((fd = safe_open(curr->fts_path, O_RDONLY | O_BINARY)) == -1) - return CL_EOPEN; - - if (onas_scth_scanfile(curr->fts_path, fd, extinfo, tharg) == CL_VIRUS); - ret = CL_VIRUS; - - close(fd); - } - } - - return ret; -} - - -static int onas_scth_handle_file(const char *pathname, struct scth_thrarg *tharg) { - int fd; - int extinfo; - int ret; - - if (!pathname) return CL_ENULLARG; - - extinfo = optget(tharg->opts, "ExtendedDetectionInfo")->enabled; - - if ((fd = safe_open(pathname, O_RDONLY | O_BINARY)) == -1) - return CL_EOPEN; - ret = onas_scth_scanfile(pathname, fd, extinfo, tharg); - - close(fd); - - return ret; -} - -void *onas_scan_th(void *arg) { - struct scth_thrarg *tharg = (struct scth_thrarg *) arg; - sigset_t sigset; - struct sigaction act; - - /* ignore all signals except SIGUSR1 */ - sigfillset(&sigset); - sigdelset(&sigset, SIGUSR1); - /* The behavior of a process is undefined after it ignores a - * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ - sigdelset(&sigset, SIGFPE); - sigdelset(&sigset, SIGILL); - sigdelset(&sigset, SIGSEGV); -#ifdef SIGBUS - sigdelset(&sigset, SIGBUS); -#endif - pthread_sigmask(SIG_SETMASK, &sigset, NULL); - memset(&act, 0, sizeof(struct sigaction)); - act.sa_handler = onas_scth_exit; - sigfillset(&(act.sa_mask)); - sigaction(SIGUSR1, &act, NULL); - sigaction(SIGSEGV, &act, NULL); - - if (NULL == tharg || NULL == tharg->pathname || NULL == tharg->opts || NULL == tharg->engine) { - logg("ScanOnAccess: Invalid thread arguments for extra scanning\n"); - goto done; - } - - if (tharg->extra_options & ONAS_SCTH_ISDIR) { - logg("*ScanOnAccess: Performing additional scanning on directory '%s'\n", tharg->pathname); - onas_scth_handle_dir(tharg->pathname, tharg); - } else if (tharg->extra_options & ONAS_SCTH_ISFILE) { - logg("*ScanOnAccess: Performing additional scanning on file '%s'\n", tharg->pathname); - onas_scth_handle_file(tharg->pathname, tharg); - } - -done: - if (NULL != tharg->pathname){ - free(tharg->pathname); - tharg->pathname = NULL; - } - if (NULL != tharg->options) { - free(tharg->options); - tharg->options = NULL; - } - if (NULL != tharg) { - free(tharg); - } - - return NULL; -} -#endif diff -Nru clamav-0.101.4+dfsg/clamd/onaccess_scth.h clamav-0.102.1+dfsg/clamd/onaccess_scth.h --- clamav-0.101.4+dfsg/clamd/onaccess_scth.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/onaccess_scth.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. - * - * Authors: Mickey Sola - * - * 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. - */ - -#ifndef __ONAS_SCTH_H -#define __ONAS_SCTH_H - -#include "shared/optparser.h" -#include "libclamav/clamav.h" - -#define ONAS_SCTH_ISDIR 0x01 -#define ONAS_SCTH_ISFILE 0x02 - -struct scth_thrarg { - uint32_t extra_options; - struct cl_scan_options *options; - const struct optstruct *opts; - const struct cl_engine *engine; - char *pathname; -}; - -void *onas_scan_th(void *arg); - -#endif diff -Nru clamav-0.101.4+dfsg/clamd/others.c clamav-0.102.1+dfsg/clamd/others.c --- clamav-0.101.4+dfsg/clamd/others.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/others.c 2019-11-20 04:42:24.000000000 +0000 @@ -29,14 +29,14 @@ #include #include #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #include #include #include #include -#ifndef _WIN32 +#ifndef _WIN32 #include #include #include @@ -84,23 +84,21 @@ free(p); } -#ifdef _WIN32 -void -virusaction (const char *filename, const char *virname, - const struct optstruct *opts) +#ifdef _WIN32 +void virusaction(const char *filename, const char *virname, + const struct optstruct *opts) { - if (optget (opts, "VirusEvent")->enabled) - logg ("^VirusEvent is not supported on this platform"); /* Yet */ + if (optget(opts, "VirusEvent")->enabled) + logg("^VirusEvent is not supported on this platform"); /* Yet */ } #else -#define VE_FILENAME "CLAM_VIRUSEVENT_FILENAME" +#define VE_FILENAME "CLAM_VIRUSEVENT_FILENAME" #define VE_VIRUSNAME "CLAM_VIRUSEVENT_VIRUSNAME" -void -virusaction (const char *filename, const char *virname, - const struct optstruct *opts) +void virusaction(const char *filename, const char *virname, + const struct optstruct *opts) { pid_t pid; const struct optstruct *opt; @@ -109,132 +107,113 @@ size_t i, j, v = 0, len; char *env[4]; - if (!(opt = optget (opts, "VirusEvent"))->enabled) + if (!(opt = optget(opts, "VirusEvent"))->enabled) return; - path = getenv ("PATH"); + path = getenv("PATH"); env[0] = path ? strdup(path) : NULL; - j = env[0] ? 1 : 0; + j = env[0] ? 1 : 0; /* Allocate env vars.. to be portable env vars should not be freed */ buffer_file = - (char *) malloc (strlen (VE_FILENAME) + strlen (filename) + 2); - if (buffer_file) - { - sprintf (buffer_file, "%s=%s", VE_FILENAME, filename); + (char *)malloc(strlen(VE_FILENAME) + strlen(filename) + 2); + if (buffer_file) { + sprintf(buffer_file, "%s=%s", VE_FILENAME, filename); env[j++] = buffer_file; } buffer_vir = - (char *) malloc (strlen (VE_VIRUSNAME) + strlen (virname) + 2); - if (buffer_vir) - { - sprintf (buffer_vir, "%s=%s", VE_VIRUSNAME, virname); + (char *)malloc(strlen(VE_VIRUSNAME) + strlen(virname) + 2); + if (buffer_vir) { + sprintf(buffer_vir, "%s=%s", VE_VIRUSNAME, virname); env[j++] = buffer_vir; } env[j++] = NULL; pt = opt->strarg; - while ((pt = strstr (pt, "%v"))) - { + while ((pt = strstr(pt, "%v"))) { pt += 2; v++; } - len = strlen (opt->strarg); + len = strlen(opt->strarg); buffer_cmd = - (char *) calloc (len + v * strlen (virname) + 1, sizeof (char)); - if (!buffer_cmd) - { + (char *)calloc(len + v * strlen(virname) + 1, sizeof(char)); + if (!buffer_cmd) { if (path) xfree(env[0]); - xfree (buffer_file); - xfree (buffer_vir); + xfree(buffer_file); + xfree(buffer_vir); return; } - for (i = 0, j = 0; i < len; i++) - { - if (i + 1 < len && opt->strarg[i] == '%' && opt->strarg[i + 1] == 'v') - { - strcat (buffer_cmd, virname); - j += strlen (virname); + for (i = 0, j = 0; i < len; i++) { + if (i + 1 < len && opt->strarg[i] == '%' && opt->strarg[i + 1] == 'v') { + strcat(buffer_cmd, virname); + j += strlen(virname); i++; - } - else - { + } else { buffer_cmd[j++] = opt->strarg[i]; } } - pthread_mutex_lock (&virusaction_lock); + pthread_mutex_lock(&virusaction_lock); /* We can only call async-signal-safe functions after fork(). */ - pid = fork (); - if (pid == 0) - { /* child */ - exit (execle ("/bin/sh", "sh", "-c", buffer_cmd, NULL, env)); - } - else if (pid > 0) - { /* parent */ - pthread_mutex_unlock (&virusaction_lock); - while (waitpid (pid, NULL, 0) == -1 && errno == EINTR); - } - else - { + pid = fork(); + if (pid == 0) { /* child */ + exit(execle("/bin/sh", "sh", "-c", buffer_cmd, NULL, env)); + } else if (pid > 0) { /* parent */ + pthread_mutex_unlock(&virusaction_lock); + while (waitpid(pid, NULL, 0) == -1 && errno == EINTR) continue; + } else { pthread_mutex_unlock(&virusaction_lock); - logg ("!VirusEvent: fork failed.\n"); + logg("!VirusEvent: fork failed.\n"); } if (path) xfree(env[0]); - xfree (buffer_cmd); - xfree (buffer_file); - xfree (buffer_vir); + xfree(buffer_cmd); + xfree(buffer_file); + xfree(buffer_vir); } #endif /* _WIN32 */ /* Function: writen Try hard to write the specified number of bytes */ -int -writen (int fd, void *buff, unsigned int count) +int writen(int fd, void *buff, unsigned int count) { int retval; unsigned int todo; unsigned char *current; - todo = count; - current = (unsigned char *) buff; + todo = count; + current = (unsigned char *)buff; - do - { - retval = write (fd, current, todo); - if (retval < 0) - { - if (errno == EINTR) - { + do { + retval = write(fd, current, todo); + if (retval < 0) { + if (errno == EINTR) { continue; } return -1; } todo -= retval; current += retval; - } - while (todo > 0); + } while (todo > 0); return count; } static int -realloc_polldata (struct fd_data *data) +realloc_polldata(struct fd_data *data) { #ifdef HAVE_POLL if (data->poll_data_nfds == data->nfds) return 0; if (data->poll_data) - free (data->poll_data); - data->poll_data = malloc (data->nfds * sizeof (*data->poll_data)); - if (!data->poll_data) - { - logg ("!realloc_polldata: Memory allocation failed for poll_data\n"); + free(data->poll_data); + data->poll_data = malloc(data->nfds * sizeof(*data->poll_data)); + if (!data->poll_data) { + logg("!realloc_polldata: Memory allocation failed for poll_data\n"); return -1; } data->poll_data_nfds = data->nfds; @@ -242,35 +221,29 @@ return 0; } -int -poll_fd (int fd, int timeout_sec, int check_signals) +int poll_fd(int fd, int timeout_sec, int check_signals) { int ret; - struct fd_data fds = FDS_INIT (NULL); + struct fd_data fds = FDS_INIT(NULL); - if (fds_add (&fds, fd, 1, timeout_sec) == -1) + if (fds_add(&fds, fd, 1, timeout_sec) == -1) return -1; - do - { - ret = fds_poll_recv (&fds, timeout_sec, check_signals, NULL); - } - while (ret == -1 && errno == EINTR); - fds_free (&fds); + do { + ret = fds_poll_recv(&fds, timeout_sec, check_signals, NULL); + } while (ret == -1 && errno == EINTR); + fds_free(&fds); return ret; } -void -fds_cleanup (struct fd_data *data) +void fds_cleanup(struct fd_data *data) { struct fd_buf *newbuf; unsigned i, j; - for (i = 0, j = 0; i < data->nfds; i++) - { - if (data->buf[i].fd < 0) - { + for (i = 0, j = 0; i < data->nfds; i++) { + if (data->buf[i].fd < 0) { if (data->buf[i].buffer) - free (data->buf[i].buffer); + free(data->buf[i].buffer); continue; } if (i != j) @@ -282,29 +255,29 @@ for (i = j; i < data->nfds; i++) data->buf[i].fd = -1; data->nfds = j; - logg ("$Number of file descriptors polled: %u fds\n", - (unsigned) data->nfds); + logg("$Number of file descriptors polled: %u fds\n", + (unsigned)data->nfds); /* Shrink buffer */ - newbuf = realloc (data->buf, j * sizeof (*newbuf)); + newbuf = realloc(data->buf, j * sizeof(*newbuf)); if (!j) data->buf = NULL; else if (newbuf) - data->buf = newbuf; /* non-fatal if shrink fails */ + data->buf = newbuf; /* non-fatal if shrink fails */ } static int -read_fd_data (struct fd_buf *buf) +read_fd_data(struct fd_buf *buf) { ssize_t n; buf->got_newdata = 1; - if (!buf->buffer) /* listen-only socket */ + if (!buf->buffer) /* listen-only socket */ return 1; if (buf->off >= buf->bufsize) return -1; - /* Read the pending packet, it may contain more than one command, but + /* Read the pending packet, it may contain more than one command, but * that is to the cmdparser to handle. * It will handle 1st command, and then move leftover to beginning of buffer */ @@ -312,69 +285,62 @@ { struct msghdr msg; struct cmsghdr *cmsg; - union - { - unsigned char buff[CMSG_SPACE (sizeof (int))]; + union { + unsigned char buff[CMSG_SPACE(sizeof(int))]; struct cmsghdr hdr; } b; struct iovec iov[1]; - if (buf->recvfd != -1) - { - logg ("$Closing unclaimed FD: %d\n", buf->recvfd); - close (buf->recvfd); + if (buf->recvfd != -1) { + logg("$Closing unclaimed FD: %d\n", buf->recvfd); + close(buf->recvfd); buf->recvfd = -1; } - memset (&msg, 0, sizeof (msg)); - iov[0].iov_base = buf->buffer + buf->off; - iov[0].iov_len = buf->bufsize - buf->off; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_control = b.buff; - msg.msg_controllen = sizeof (b.buff); + memset(&msg, 0, sizeof(msg)); + iov[0].iov_base = buf->buffer + buf->off; + iov[0].iov_len = buf->bufsize - buf->off; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = b.buff; + msg.msg_controllen = sizeof(b.buff); - n = recvmsg (buf->fd, &msg, 0); + n = recvmsg(buf->fd, &msg, 0); if (n < 0) return -1; - if (msg.msg_flags & MSG_TRUNC) - { - logg ("^Message truncated at %d bytes\n", (int) n); + if (msg.msg_flags & MSG_TRUNC) { + logg("^Message truncated at %d bytes\n", (int)n); return -1; } - if (msg.msg_flags & MSG_CTRUNC) - { + if (msg.msg_flags & MSG_CTRUNC) { if (msg.msg_controllen > 0) - logg ("^Control message truncated at %d bytes, %d data read\n", (int) msg.msg_controllen, (int) n); + logg("^Control message truncated at %d bytes, %d data read\n", (int)msg.msg_controllen, (int)n); else - logg ("^Control message truncated, no control data received, %d bytes read" + logg("^Control message truncated, no control data received, %d bytes read" #ifdef C_LINUX - "(Is SELinux/AppArmor enabled, and blocking file descriptor passing?)" + "(Is SELinux/AppArmor enabled, and blocking file descriptor passing?)" #endif - "\n", (int) n); + "\n", + (int)n); return -1; } - if (msg.msg_controllen) - { - for (cmsg = CMSG_FIRSTHDR (&msg); cmsg != NULL; - cmsg = CMSG_NXTHDR (&msg, cmsg)) - { - if (cmsg->cmsg_len == CMSG_LEN (sizeof (int)) && + if (msg.msg_controllen) { + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && - cmsg->cmsg_type == SCM_RIGHTS) - { - if (buf->recvfd != -1) - { - logg ("$Unclaimed file descriptor received. closing: %d\n", buf->recvfd); - close (buf->recvfd); + cmsg->cmsg_type == SCM_RIGHTS) { + if (buf->recvfd != -1) { + logg("$Unclaimed file descriptor received. closing: %d\n", buf->recvfd); + close(buf->recvfd); } - buf->recvfd = *(int *) CMSG_DATA (cmsg); - logg ("$Receveived a file descriptor: %d\n", buf->recvfd); + buf->recvfd = *(int *)CMSG_DATA(cmsg); + logg("$Receveived a file descriptor: %d\n", buf->recvfd); } } } } #else - n = recv (buf->fd, buf->buffer + buf->off, buf->bufsize - buf->off, 0); + n = recv(buf->fd, buf->buffer + buf->off, buf->bufsize - buf->off, 0); if (n < 0) return -1; #endif @@ -383,120 +349,104 @@ } static int -buf_init (struct fd_buf *buf, int listen_only, int timeout) +buf_init(struct fd_buf *buf, int listen_only, int timeout) { - buf->off = 0; + buf->off = 0; buf->got_newdata = 0; - buf->recvfd = -1; - buf->mode = MODE_COMMAND; - buf->id = 0; - buf->dumpfd = -1; - buf->chunksize = 0; - buf->quota = 0; - buf->dumpname = NULL; - buf->group = NULL; - buf->term = '\0'; - if (!listen_only) - { - if (!buf->buffer) - { + buf->recvfd = -1; + buf->mode = MODE_COMMAND; + buf->id = 0; + buf->dumpfd = -1; + buf->chunksize = 0; + buf->quota = 0; + buf->dumpname = NULL; + buf->group = NULL; + buf->term = '\0'; + if (!listen_only) { + if (!buf->buffer) { buf->bufsize = PATH_MAX + 8; /* plus extra space for a \0 so we can make sure every command is \0 * terminated */ - if (!(buf->buffer = malloc (buf->bufsize + 1))) - { - logg ("!add_fd: Memory allocation failed for command buffer\n"); + if (!(buf->buffer = malloc(buf->bufsize + 1))) { + logg("!add_fd: Memory allocation failed for command buffer\n"); return -1; } } - } - else - { + } else { if (buf->buffer) - free (buf->buffer); + free(buf->buffer); buf->bufsize = 0; - buf->buffer = NULL; + buf->buffer = NULL; } - if (timeout) - { - time (&buf->timeout_at); + if (timeout) { + time(&buf->timeout_at); buf->timeout_at += timeout; - } - else - { + } else { buf->timeout_at = 0; } return 0; } -int -fds_add (struct fd_data *data, int fd, int listen_only, int timeout) +int fds_add(struct fd_data *data, int fd, int listen_only, int timeout) { struct fd_buf *buf; unsigned n; - if (fd < 0) - { - logg ("!add_fd: invalid fd passed to add_fd\n"); + if (fd < 0) { + logg("!add_fd: invalid fd passed to add_fd\n"); return -1; } /* we may already have this fd, if * the old FD got closed, and the kernel reused the FD */ for (n = 0; n < data->nfds; n++) - if (data->buf[n].fd == fd) - { + if (data->buf[n].fd == fd) { /* clear stale data in buffer */ - if (buf_init (&data->buf[n], listen_only, timeout) < 0) + if (buf_init(&data->buf[n], listen_only, timeout) < 0) return -1; return 0; } n++; - buf = realloc (data->buf, n * sizeof (*buf)); - if (!buf) - { - logg ("!add_fd: Memory allocation failed for fd_buf\n"); + buf = realloc(data->buf, n * sizeof(*buf)); + if (!buf) { + logg("!add_fd: Memory allocation failed for fd_buf\n"); return -1; } - data->buf = buf; - data->nfds = n; + data->buf = buf; + data->nfds = n; data->buf[n - 1].buffer = NULL; - if (buf_init (&data->buf[n - 1], listen_only, timeout) < 0) + if (buf_init(&data->buf[n - 1], listen_only, timeout) < 0) return -1; data->buf[n - 1].fd = fd; return 0; } static inline void -fds_lock (struct fd_data *data) +fds_lock(struct fd_data *data) { if (data->buf_mutex) - pthread_mutex_lock (data->buf_mutex); + pthread_mutex_lock(data->buf_mutex); } static inline void -fds_unlock (struct fd_data *data) +fds_unlock(struct fd_data *data) { if (data->buf_mutex) - pthread_mutex_unlock (data->buf_mutex); + pthread_mutex_unlock(data->buf_mutex); } -void -fds_remove (struct fd_data *data, int fd) +void fds_remove(struct fd_data *data, int fd) { size_t i; - fds_lock (data); - if (data->buf) - { - for (i = 0; i < data->nfds; i++) - { - if (data->buf[i].fd == fd) - { + fds_lock(data); + if (data->buf) { + for (i = 0; i < data->nfds; i++) { + if (data->buf[i].fd == fd) { data->buf[i].fd = -1; break; } } } - fds_unlock (data); + fds_unlock(data); } #define BUFFSIZE 1024 @@ -509,9 +459,8 @@ * Must be called with buf_mutex lock held. */ /* TODO: handle ReadTimeout */ -int -fds_poll_recv (struct fd_data *data, int timeout, int check_signals, - void *event) +int fds_poll_recv(struct fd_data *data, int timeout, int check_signals, + void *event) { unsigned fdsok = data->nfds; size_t i; @@ -521,33 +470,28 @@ UNUSEDPARAM(event); /* we must have at least one fd, the control fd! */ - fds_cleanup (data); + fds_cleanup(data); #ifndef _WIN32 if (!data->nfds) return 0; #endif - for (i = 0; i < data->nfds; i++) - { + for (i = 0; i < data->nfds; i++) { data->buf[i].got_newdata = 0; } - time (&now); + time(&now); if (timeout > 0) closest_timeout = now + timeout; else closest_timeout = 0; - for (i = 0; i < data->nfds; i++) - { + for (i = 0; i < data->nfds; i++) { time_t timeout_at = data->buf[i].timeout_at; - if (timeout_at && timeout_at < now) - { + if (timeout_at && timeout_at < now) { /* timed out */ data->buf[i].got_newdata = -2; /* we must return immediately from poll/select, we have a timeout! */ closest_timeout = now; - } - else - { + } else { if (!closest_timeout) closest_timeout = timeout_at; else if (timeout_at && timeout_at < closest_timeout) @@ -559,7 +503,7 @@ else timeout = -1; if (timeout > 0) - logg ("$fds_poll_recv: timeout after %d seconds\n", timeout); + logg("$fds_poll_recv: timeout after %d seconds\n", timeout); #ifdef HAVE_POLL /* Use poll() if available, preferred because: * - can poll any number of FDs @@ -569,65 +513,56 @@ * recv() may still block according to the manpage */ - if (realloc_polldata (data) == -1) + if (realloc_polldata(data) == -1) return -1; - if (timeout > 0) - { + if (timeout > 0) { /* seconds to ms */ timeout *= 1000; } - for (i = 0; i < data->nfds; i++) - { - data->poll_data[i].fd = data->buf[i].fd; - data->poll_data[i].events = POLLIN; + for (i = 0; i < data->nfds; i++) { + data->poll_data[i].fd = data->buf[i].fd; + data->poll_data[i].events = POLLIN; data->poll_data[i].revents = 0; } - do - { + do { int n = data->nfds; - fds_unlock (data); + fds_unlock(data); #ifdef _WIN32 - retval = poll_with_event (data->poll_data, n, timeout, event); + retval = poll_with_event(data->poll_data, n, timeout, event); #else - retval = poll (data->poll_data, n, timeout); + retval = poll(data->poll_data, n, timeout); #endif - fds_lock (data); + fds_lock(data); - if (retval > 0) - { + if (retval > 0) { fdsok = 0; /* nfds may change during poll, but not * poll_data_nfds */ - for (i = 0; i < data->poll_data_nfds; i++) - { + for (i = 0; i < data->poll_data_nfds; i++) { short revents; if (data->buf[i].fd < 0) continue; - if (data->buf[i].fd != data->poll_data[i].fd) - { + if (data->buf[i].fd != data->poll_data[i].fd) { /* should never happen */ - logg ("!poll_recv_fds FD mismatch\n"); + logg("!poll_recv_fds FD mismatch\n"); continue; } revents = data->poll_data[i].revents; - if (revents & (POLLIN | POLLHUP)) - { - logg ("$Received POLLIN|POLLHUP on fd %d\n", - data->poll_data[i].fd); + if (revents & (POLLIN | POLLHUP)) { + logg("$Received POLLIN|POLLHUP on fd %d\n", + data->poll_data[i].fd); } #ifndef _WIN32 - if (revents & POLLHUP) - { + if (revents & POLLHUP) { /* avoid SHUT_WR problem on Mac OS X */ - int ret = send (data->poll_data[i].fd, &n, 0, 0); + int ret = send(data->poll_data[i].fd, &n, 0, 0); if (!ret || (ret == -1 && errno == EINTR)) revents &= ~POLLHUP; } #endif - if (revents & POLLIN) - { - int ret = read_fd_data (&data->buf[i]); + if (revents & POLLIN) { + int ret = read_fd_data(&data->buf[i]); /* Data available to be read */ if (ret == -1) revents |= POLLERR; @@ -635,168 +570,139 @@ revents = POLLHUP; } - if (revents & (POLLHUP | POLLERR | POLLNVAL)) - { - if (revents & (POLLHUP | POLLNVAL)) - { + if (revents & (POLLHUP | POLLERR | POLLNVAL)) { + if (revents & (POLLHUP | POLLNVAL)) { /* remote disconnected */ - logg ("*Client disconnected (FD %d)\n", - data->poll_data[i].fd); - } - else - { + logg("*Client disconnected (FD %d)\n", + data->poll_data[i].fd); + } else { /* error on file descriptor */ - logg ("^Error condition on fd %d\n", - data->poll_data[i].fd); + logg("^Error condition on fd %d\n", + data->poll_data[i].fd); } data->buf[i].got_newdata = -1; - } - else - { + } else { fdsok++; } } } - } - while (retval == -1 && !check_signals && errno == EINTR); + } while (retval == -1 && !check_signals && errno == EINTR); #else { fd_set rfds; struct timeval tv; int maxfd = -1; - for (i = 0; i < data->nfds; i++) - { + for (i = 0; i < data->nfds; i++) { int fd = data->buf[i].fd; - if (fd >= FD_SETSIZE) - { - logg ("!File descriptor is too high for FD_SET\n"); + if (fd >= FD_SETSIZE) { + logg("!File descriptor is too high for FD_SET\n"); return -1; } - maxfd = MAX (maxfd, fd); + maxfd = MAX(maxfd, fd); } - do - { - FD_ZERO (&rfds); - for (i = 0; i < data->nfds; i++) - { + do { + FD_ZERO(&rfds); + for (i = 0; i < data->nfds; i++) { int fd = data->buf[i].fd; if (fd >= 0) - FD_SET (fd, &rfds); + FD_SET(fd, &rfds); } - tv.tv_sec = timeout; + tv.tv_sec = timeout; tv.tv_usec = 0; - fds_unlock (data); + fds_unlock(data); retval = - select (maxfd + 1, &rfds, NULL, NULL, - timeout >= 0 ? &tv : NULL); - fds_lock (data); - if (retval > 0) - { + select(maxfd + 1, &rfds, NULL, NULL, + timeout >= 0 ? &tv : NULL); + fds_lock(data); + if (retval > 0) { fdsok = data->nfds; - for (i = 0; i < data->nfds; i++) - { - if (data->buf[i].fd < 0) - { + for (i = 0; i < data->nfds; i++) { + if (data->buf[i].fd < 0) { fdsok--; continue; } - if (FD_ISSET (data->buf[i].fd, &rfds)) - { - int ret = read_fd_data (&data->buf[i]); - if (ret == -1 || !ret) - { + if (FD_ISSET(data->buf[i].fd, &rfds)) { + int ret = read_fd_data(&data->buf[i]); + if (ret == -1 || !ret) { if (ret == -1) - logg ("!Error condition on fd %d\n", - data->buf[i].fd); - else - { + logg("!Error condition on fd %d\n", + data->buf[i].fd); + else { /* avoid SHUT_WR problem on Mac OS X */ - int ret = send (data->buf[i].fd, &i, 0, 0); + int ret = send(data->buf[i].fd, &i, 0, 0); if (!ret || (ret == -1 && errno == EINTR)) continue; - logg ("*Client disconnected\n"); + logg("*Client disconnected\n"); } data->buf[i].got_newdata = -1; } } } } - if (retval < 0 && errno == EBADF) - { + if (retval < 0 && errno == EBADF) { /* unlike poll(), select() won't tell us which FD is bad, so * we have to check them one by one. */ - tv.tv_sec = 0; + tv.tv_sec = 0; tv.tv_usec = 0; /* with tv == 0 it doesn't check for EBADF */ - FD_ZERO (&rfds); - for (i = 0; i < data->nfds; i++) - { + FD_ZERO(&rfds); + for (i = 0; i < data->nfds; i++) { if (data->buf[i].fd == -1) continue; - FD_SET (data->buf[i].fd, &rfds); - do - { + FD_SET(data->buf[i].fd, &rfds); + do { retval = - select (data->buf[i].fd + 1, &rfds, NULL, NULL, - &tv); - } - while (retval == -1 && errno == EINTR); - if (retval == -1) - { + select(data->buf[i].fd + 1, &rfds, NULL, NULL, + &tv); + } while (retval == -1 && errno == EINTR); + if (retval == -1) { data->buf[i].fd = -1; - } - else - { - FD_CLR (data->buf[i].fd, &rfds); + } else { + FD_CLR(data->buf[i].fd, &rfds); } } retval = -1; - errno = EINTR; + errno = EINTR; continue; } - } - while (retval == -1 && !check_signals && errno == EINTR); + } while (retval == -1 && !check_signals && errno == EINTR); } #endif - if (retval == -1 && errno != EINTR) - { + if (retval == -1 && errno != EINTR) { char err[128]; #ifdef HAVE_POLL - logg ("!poll_recv_fds: poll failed: %s\n", - cli_strerror (errno, err, sizeof (err))); + logg("!poll_recv_fds: poll failed: %s\n", + cli_strerror(errno, err, sizeof(err))); #else - logg ("!poll_recv_fds: select failed: %s\n", - cli_strerror (errno, err, sizeof (err))); + logg("!poll_recv_fds: select failed: %s\n", + cli_strerror(errno, err, sizeof(err))); #endif } return retval; } -void -fds_free (struct fd_data *data) +void fds_free(struct fd_data *data) { unsigned i; - fds_lock (data); - for (i = 0; i < data->nfds; i++) - { - if (data->buf[i].buffer) - { - free (data->buf[i].buffer); + fds_lock(data); + for (i = 0; i < data->nfds; i++) { + if (data->buf[i].buffer) { + free(data->buf[i].buffer); } } if (data->buf) - free (data->buf); + free(data->buf); #ifdef HAVE_POLL if (data->poll_data) - free (data->poll_data); + free(data->poll_data); #endif - data->buf = NULL; + data->buf = NULL; data->nfds = 0; - fds_unlock (data); + fds_unlock(data); } diff -Nru clamav-0.101.4+dfsg/clamd/others.h clamav-0.102.1+dfsg/clamd/others.h --- clamav-0.101.4+dfsg/clamd/others.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/others.h 2019-11-20 04:42:24.000000000 +0000 @@ -35,7 +35,8 @@ MODE_COMMAND, MODE_STREAM, MODE_WAITREPLY, - MODE_WAITANCILL + MODE_WAITANCILL, + MODE_HANDSHAKE }; struct fd_buf { @@ -69,9 +70,15 @@ }; #ifdef HAVE_POLL -#define FDS_INIT(mutex) { (mutex), NULL, 0, NULL, 0} +#define FDS_INIT(mutex) \ + { \ + (mutex), NULL, 0, NULL, 0 \ + } #else -#define FDS_INIT(mutex) { (mutex), NULL, 0} +#define FDS_INIT(mutex) \ + { \ + (mutex), NULL, 0 \ + } #endif int poll_fd(int fd, int timeout_sec, int check_signals); diff -Nru clamav-0.101.4+dfsg/clamd/priv_fts.h clamav-0.102.1+dfsg/clamd/priv_fts.h --- clamav-0.101.4+dfsg/clamd/priv_fts.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/priv_fts.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -#include "clamav-config.h" - -#if HAVE_SYSTEM_LFS_FTS -#include - -static inline FTSENT *_priv_fts_children(FTS *ftsp, int options) -{ - return fts_children(ftsp, options); -} - -static inline int _priv_fts_close(FTS *ftsp) -{ - return fts_close(ftsp); -} - -static inline FTS *_priv_fts_open (char * const *path_argv, int options, - int (*compar)(const FTSENT **, const FTSENT **)) -{ - return fts_open(path_argv, options, compar); -} - -static inline FTSENT *_priv_fts_read (FTS *ftsp) -{ - return fts_read(ftsp); -} - -static inline int _priv_fts_set (FTS *ftsp, FTSENT *f, int options) -{ - return fts_set(ftsp, f, options); -} - -#else -/* File tree traversal functions declarations. - Copyright (C) 1994-2015 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - . */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)fts.h 8.3 (Berkeley) 8/14/94 - */ - -#ifndef _FTS_H -#define _FTS_H 1 - -#include - - -typedef struct { - struct _ftsent *fts_cur; /* current node */ - struct _ftsent *fts_child; /* linked list of children */ - struct _ftsent **fts_array; /* sort array */ - dev_t fts_dev; /* starting device # */ - char *fts_path; /* path for this descent */ - int fts_rfd; /* fd for root */ - int fts_pathlen; /* sizeof(path) */ - int fts_nitems; /* elements in the sort array */ - int (*fts_compar) (const void *, const void *); /* compare fn */ - -#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ -#define FTS_LOGICAL 0x0002 /* logical walk */ -#define FTS_NOCHDIR 0x0004 /* don't change directories */ -#define FTS_NOSTAT 0x0008 /* don't get stat info */ -#define FTS_PHYSICAL 0x0010 /* physical walk */ -#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ -#define FTS_XDEV 0x0040 /* don't cross devices */ -#define FTS_WHITEOUT 0x0080 /* return whiteout information */ -#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ - -#define FTS_NAMEONLY 0x0100 /* (private) child names only */ -#define FTS_STOP 0x0200 /* (private) unrecoverable error */ - int fts_options; /* fts_open options, global flags */ -} FTS; - -#ifdef __USE_LARGEFILE64 -typedef struct { - struct _ftsent64 *fts_cur; /* current node */ - struct _ftsent64 *fts_child; /* linked list of children */ - struct _ftsent64 **fts_array; /* sort array */ - dev_t fts_dev; /* starting device # */ - char *fts_path; /* path for this descent */ - int fts_rfd; /* fd for root */ - int fts_pathlen; /* sizeof(path) */ - int fts_nitems; /* elements in the sort array */ - int (*fts_compar) (const void *, const void *); /* compare fn */ - int fts_options; /* fts_open options, global flags */ -} FTS64; -#endif - -typedef struct _ftsent { - struct _ftsent *fts_cycle; /* cycle node */ - struct _ftsent *fts_parent; /* parent directory */ - struct _ftsent *fts_link; /* next file in directory */ - long fts_number; /* local numeric value */ - void *fts_pointer; /* local address value */ - char *fts_accpath; /* access path */ - char *fts_path; /* root path */ - int fts_errno; /* errno for this node */ - int fts_symfd; /* fd for symlink */ - u_short fts_pathlen; /* strlen(fts_path) */ - u_short fts_namelen; /* strlen(fts_name) */ - - ino_t fts_ino; /* inode */ - dev_t fts_dev; /* device */ - nlink_t fts_nlink; /* link count */ - -#define FTS_ROOTPARENTLEVEL -1 -#define FTS_ROOTLEVEL 0 - short fts_level; /* depth (-1 to N) */ - -#define FTS_D 1 /* preorder directory */ -#define FTS_DC 2 /* directory that causes cycles */ -#define FTS_DEFAULT 3 /* none of the above */ -#define FTS_DNR 4 /* unreadable directory */ -#define FTS_DOT 5 /* dot or dot-dot */ -#define FTS_DP 6 /* postorder directory */ -#define FTS_ERR 7 /* error; errno is set */ -#define FTS_F 8 /* regular file */ -#define FTS_INIT 9 /* initialized only */ -#define FTS_NS 10 /* stat(2) failed */ -#define FTS_NSOK 11 /* no stat(2) requested */ -#define FTS_SL 12 /* symbolic link */ -#define FTS_SLNONE 13 /* symbolic link without target */ -#define FTS_W 14 /* whiteout object */ - u_short fts_info; /* user flags for FTSENT structure */ - -#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ -#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ - u_short fts_flags; /* private flags for FTSENT structure */ - -#define FTS_AGAIN 1 /* read node again */ -#define FTS_FOLLOW 2 /* follow symbolic link */ -#define FTS_NOINSTR 3 /* no instructions */ -#define FTS_SKIP 4 /* discard node */ - u_short fts_instr; /* fts_set() instructions */ - - struct stat *fts_statp; /* stat(2) information */ - char fts_name[1]; /* file name */ -} FTSENT; - -#ifdef __USE_LARGEFILE64 -typedef struct _ftsent64 { - struct _ftsent64 *fts_cycle; /* cycle node */ - struct _ftsent64 *fts_parent; /* parent directory */ - struct _ftsent64 *fts_link; /* next file in directory */ - long fts_number; /* local numeric value */ - void *fts_pointer; /* local address value */ - char *fts_accpath; /* access path */ - char *fts_path; /* root path */ - int fts_errno; /* errno for this node */ - int fts_symfd; /* fd for symlink */ - u_short fts_pathlen; /* strlen(fts_path) */ - u_short fts_namelen; /* strlen(fts_name) */ - - ino64_t fts_ino; /* inode */ - dev_t fts_dev; /* device */ - nlink_t fts_nlink; /* link count */ - - short fts_level; /* depth (-1 to N) */ - - u_short fts_info; /* user flags for FTSENT structure */ - - u_short fts_flags; /* private flags for FTSENT structure */ - - u_short fts_instr; /* fts_set() instructions */ - - struct stat64 *fts_statp; /* stat(2) information */ - char fts_name[1]; /* file name */ -} FTSENT64; -#endif - -__BEGIN_DECLS -FTSENT *_priv_fts_children (FTS *, int); -int _priv_fts_close (FTS *); -FTS *_priv_fts_open (char * const *, int, - int (*)(const FTSENT **, const FTSENT **)); -FTSENT *_priv_fts_read (FTS *); -int _priv_fts_set (FTS *, FTSENT *, int) __THROW; -__END_DECLS - -#endif /* fts.h */ -#endif diff -Nru clamav-0.101.4+dfsg/clamd/scanner.c clamav-0.102.1+dfsg/clamd/scanner.c --- clamav-0.101.4+dfsg/clamd/scanner.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/scanner.c 2019-11-20 04:42:24.000000000 +0000 @@ -26,14 +26,14 @@ #include #include #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #include #include #include #include -#ifndef _WIN32 +#ifndef _WIN32 #include #include #include @@ -45,11 +45,6 @@ #endif #include -#if defined(HAVE_READDIR_R_3) || defined(HAVE_READDIR_R_2) -#include -#include -#endif - #include "libclamav/clamav.h" #include "libclamav/others.h" #include "libclamav/scanners.h" @@ -81,18 +76,18 @@ UNUSEDPARAM(fullmsg); switch (severity) { - case CL_MSG_ERROR: - logg("^[LibClamAV] %s: %s", filename, msg); - break; - case CL_MSG_WARN: - logg("~[LibClamAV] %s: %s", filename, msg); - break; - case CL_MSG_INFO_VERBOSE: - logg("*[LibClamAV] %s: %s", filename, msg); - break; - default: - logg("$[LibClamAV] %s: %s", filename, msg); - break; + case CL_MSG_ERROR: + logg("^[LibClamAV] %s: %s", filename, msg); + break; + case CL_MSG_WARN: + logg("~[LibClamAV] %s: %s", filename, msg); + break; + case CL_MSG_INFO_VERBOSE: + logg("*[LibClamAV] %s: %s", filename, msg); + break; + default: + logg("$[LibClamAV] %s: %s", filename, msg); + break; } } @@ -103,7 +98,7 @@ UNUSEDPARAM(virname); if (!c) - return; + return; c->virsize = size; strncpy(c->virhash, (const char *)md5, 32); c->virhash[32] = '\0'; @@ -111,10 +106,12 @@ void clamd_virus_found_cb(int fd, const char *virname, void *ctx) { - struct cb_context *c = ctx; + struct cb_context *c = ctx; struct scan_cb_data *d = c->scandata; const char *fname; - + + UNUSEDPARAM(fd); + if (d == NULL) return; if (!(d->options->general & CL_SCAN_GENERAL_ALLMATCHES) && !(d->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)) @@ -127,7 +124,7 @@ if (virname) { d->infected++; conn_reply_virus(d->conn, fname, virname); - if(c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled) + if (c->virsize > 0 && optget(d->opts, "ExtendedDetectionInfo")->enabled) logg("~%s: %s(%s:%llu) FOUND\n", fname, virname, c->virhash, c->virsize); logg("~%s: %s FOUND\n", fname, virname); } @@ -139,135 +136,135 @@ int scan_callback(STATBUF *sb, char *filename, const char *msg, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { struct scan_cb_data *scandata = data->data; - const char *virname = NULL; + const char *virname = NULL; int ret; int type = scandata->type; struct cb_context context; - /* detect disconnected socket, + /* detect disconnected socket, * this should NOT detect half-shutdown sockets (SHUT_WR) */ if (send(scandata->conn->sd, &ret, 0, 0) == -1 && errno != EINTR) { - logg("$Client disconnected while command was active!\n"); - thrmgr_group_terminate(scandata->conn->group); - if (reason == visit_file) - free(filename); - return CL_BREAK; + logg("$Client disconnected while command was active!\n"); + thrmgr_group_terminate(scandata->conn->group); + if (reason == visit_file) + free(filename); + return CL_BREAK; } if (thrmgr_group_need_terminate(scandata->conn->group)) { - logg("^Client disconnected while scanjob was active\n"); - if (reason == visit_file) - free(filename); - return CL_BREAK; + logg("^Client disconnected while scanjob was active\n"); + if (reason == visit_file) + free(filename); + return CL_BREAK; } scandata->total++; switch (reason) { - case error_mem: - if (msg) - logg("!Memory allocation failed during cli_ftw() on %s\n", - msg); - else - logg("!Memory allocation failed during cli_ftw()\n"); - scandata->errors++; - return CL_EMEM; - case error_stat: - conn_reply_errno(scandata->conn, msg, "lstat() failed:"); - logg("^lstat() failed on: %s\n", msg); - scandata->errors++; - return CL_SUCCESS; - case warning_skipped_dir: - logg("^Directory recursion limit reached, skipping %s\n", - msg); - return CL_SUCCESS; - case warning_skipped_link: - logg("$Skipping symlink: %s\n", msg); - return CL_SUCCESS; - case warning_skipped_special: - if (msg == scandata->toplevel_path) - conn_reply(scandata->conn, msg, "Not supported file type", "ERROR"); - logg("*Not supported file type: %s\n", msg); - return CL_SUCCESS; - case visit_directory_toplev: - return CL_SUCCESS; - case visit_file: - break; + case error_mem: + if (msg) + logg("!Memory allocation failed during cli_ftw() on %s\n", + msg); + else + logg("!Memory allocation failed during cli_ftw()\n"); + scandata->errors++; + return CL_EMEM; + case error_stat: + conn_reply_errno(scandata->conn, msg, "lstat() failed:"); + logg("^lstat() failed on: %s\n", msg); + scandata->errors++; + return CL_SUCCESS; + case warning_skipped_dir: + logg("^Directory recursion limit reached, skipping %s\n", + msg); + return CL_SUCCESS; + case warning_skipped_link: + logg("$Skipping symlink: %s\n", msg); + return CL_SUCCESS; + case warning_skipped_special: + if (msg == scandata->toplevel_path) + conn_reply(scandata->conn, msg, "Not supported file type", "ERROR"); + logg("*Not supported file type: %s\n", msg); + return CL_SUCCESS; + case visit_directory_toplev: + return CL_SUCCESS; + case visit_file: + break; } - /* check whether the file is excluded */ + /* check whether the file is excluded */ #ifdef C_LINUX - if(procdev && sb && (sb->st_dev == procdev)) { - free(filename); - return CL_SUCCESS; + if (procdev && sb && (sb->st_dev == procdev)) { + free(filename); + return CL_SUCCESS; } #endif - if(sb && sb->st_size == 0) { /* empty file */ - if (msg == scandata->toplevel_path) - conn_reply_single(scandata->conn, filename, "Empty file"); - free(filename); - return CL_SUCCESS; + if (sb && sb->st_size == 0) { /* empty file */ + if (msg == scandata->toplevel_path) + conn_reply_single(scandata->conn, filename, "Empty file"); + free(filename); + return CL_SUCCESS; } if (type == TYPE_MULTISCAN) { - client_conn_t *client_conn = (client_conn_t *) calloc(1, sizeof(struct client_conn_tag)); - if(client_conn) { - client_conn->scanfd = -1; - client_conn->sd = scandata->odesc; - client_conn->filename = filename; - client_conn->cmdtype = COMMAND_MULTISCANFILE; - client_conn->term = scandata->conn->term; - client_conn->options = scandata->options; - client_conn->opts = scandata->opts; - client_conn->group = scandata->group; - if(cl_engine_addref(scandata->engine)) { - logg("!cl_engine_addref() failed\n"); - free(filename); - free(client_conn); - return CL_EMEM; - } else { - client_conn->engine = scandata->engine; - pthread_mutex_lock(&reload_mutex); - client_conn->engine_timestamp = reloaded_time; - pthread_mutex_unlock(&reload_mutex); - if(!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) { - logg("!thread dispatch failed\n"); - cl_engine_free(scandata->engine); - free(filename); - free(client_conn); - return CL_EMEM; - } - } - } else { - logg("!Can't allocate memory for client_conn\n"); - scandata->errors++; - free(filename); - return CL_EMEM; - } - return CL_SUCCESS; + client_conn_t *client_conn = (client_conn_t *)calloc(1, sizeof(struct client_conn_tag)); + if (client_conn) { + client_conn->scanfd = -1; + client_conn->sd = scandata->odesc; + client_conn->filename = filename; + client_conn->cmdtype = COMMAND_MULTISCANFILE; + client_conn->term = scandata->conn->term; + client_conn->options = scandata->options; + client_conn->opts = scandata->opts; + client_conn->group = scandata->group; + if (cl_engine_addref(scandata->engine)) { + logg("!cl_engine_addref() failed\n"); + free(filename); + free(client_conn); + return CL_EMEM; + } else { + client_conn->engine = scandata->engine; + pthread_mutex_lock(&reload_mutex); + client_conn->engine_timestamp = reloaded_time; + pthread_mutex_unlock(&reload_mutex); + if (!thrmgr_group_dispatch(scandata->thr_pool, scandata->group, client_conn, 1)) { + logg("!thread dispatch failed\n"); + cl_engine_free(scandata->engine); + free(filename); + free(client_conn); + return CL_EMEM; + } + } + } else { + logg("!Can't allocate memory for client_conn\n"); + scandata->errors++; + free(filename); + return CL_EMEM; + } + return CL_SUCCESS; } if (access(filename, R_OK)) { - if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) { - free(filename); - return CL_ETIMEOUT; - } - logg("*Access denied: %s\n", filename); - scandata->errors++; - free(filename); - return CL_SUCCESS; + if (conn_reply(scandata->conn, filename, "Access denied.", "ERROR") == -1) { + free(filename); + return CL_ETIMEOUT; + } + logg("*Access denied: %s\n", filename); + scandata->errors++; + free(filename); + return CL_SUCCESS; } thrmgr_setactivetask(filename, NULL); context.filename = filename; - context.virsize = 0; + context.virsize = 0; context.scandata = scandata; - ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context); + ret = cl_scanfile_callback(filename, &virname, &scandata->scanned, scandata->engine, scandata->options, &context); thrmgr_setactivetask(NULL, NULL); if (thrmgr_group_need_terminate(scandata->conn->group)) { - free(filename); - logg("*Client disconnected while scanjob was active\n"); - return ret == CL_ETIMEOUT ? ret : CL_BREAK; + free(filename); + logg("*Client disconnected while scanjob was active\n"); + return ret == CL_ETIMEOUT ? ret : CL_BREAK; } if ((ret == CL_VIRUS) && (virname == NULL)) { @@ -277,46 +274,46 @@ if (ret == CL_VIRUS) { - if (scandata->options->general & CL_SCAN_GENERAL_ALLMATCHES || (scandata->infected && scandata->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)) { - if(optget(scandata->opts, "PreludeEnable")->enabled){ + if (scandata->options->general & CL_SCAN_GENERAL_ALLMATCHES || (scandata->infected && scandata->options->general & CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE)) { + if (optget(scandata->opts, "PreludeEnable")->enabled) { prelude_logging(filename, virname, context.virhash, context.virsize); } virusaction(filename, virname, scandata->opts); } else { - scandata->infected++; + scandata->infected++; if (conn_reply_virus(scandata->conn, filename, virname) == -1) { free(filename); return CL_ETIMEOUT; } - if(optget(scandata->opts, "PreludeEnable")->enabled){ + if (optget(scandata->opts, "PreludeEnable")->enabled) { prelude_logging(filename, virname, context.virhash, context.virsize); } - if(context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled) + if (context.virsize && optget(scandata->opts, "ExtendedDetectionInfo")->enabled) logg("~%s: %s(%s:%llu) FOUND\n", filename, virname, context.virhash, context.virsize); else logg("~%s: %s FOUND\n", filename, virname); virusaction(filename, virname, scandata->opts); } } else if (ret != CL_CLEAN) { - scandata->errors++; - if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) { - free(filename); - return CL_ETIMEOUT; - } - logg("~%s: %s ERROR\n", filename, cl_strerror(ret)); + scandata->errors++; + if (conn_reply(scandata->conn, filename, cl_strerror(ret), "ERROR") == -1) { + free(filename); + return CL_ETIMEOUT; + } + logg("~%s: %s ERROR\n", filename, cl_strerror(ret)); } else if (logok) { - logg("~%s: OK\n", filename); + logg("~%s: OK\n", filename); } free(filename); - if(ret == CL_EMEM) /* stop scanning */ - return ret; + if (ret == CL_EMEM) /* stop scanning */ + return ret; if (type == TYPE_SCAN) { - /* virus -> break */ - return ret; + /* virus -> break */ + return ret; } /* keep scanning always */ @@ -325,280 +322,279 @@ int scan_pathchk(const char *path, struct cli_ftw_cbdata *data) { - struct scan_cb_data *scandata = data->data; - const struct optstruct *opt; - STATBUF statbuf; - - if((opt = optget(scandata->opts, "ExcludePath"))->enabled) { - while(opt) { - if(match_regex(path, opt->strarg) == 1) { - if(scandata->type != TYPE_MULTISCAN) - conn_reply_single(scandata->conn, path, "Excluded"); - return 1; - } - opt = (const struct optstruct *) opt->nextarg; - } - } - - if(!optget(scandata->opts, "CrossFilesystems")->enabled) { - if(CLAMSTAT(path, &statbuf) == 0) { - if(statbuf.st_dev != scandata->dev) { - if(scandata->type != TYPE_MULTISCAN) - conn_reply_single(scandata->conn, path, "Excluded (another filesystem)"); - return 1; - } - } + struct scan_cb_data *scandata = data->data; + const struct optstruct *opt; + STATBUF statbuf; + + if ((opt = optget(scandata->opts, "ExcludePath"))->enabled) { + while (opt) { + if (match_regex(path, opt->strarg) == 1) { + if (scandata->type != TYPE_MULTISCAN) + conn_reply_single(scandata->conn, path, "Excluded"); + return 1; + } + opt = (const struct optstruct *)opt->nextarg; + } + } + + if (!optget(scandata->opts, "CrossFilesystems")->enabled) { + if (CLAMSTAT(path, &statbuf) == 0) { + if (statbuf.st_dev != scandata->dev) { + if (scandata->type != TYPE_MULTISCAN) + conn_reply_single(scandata->conn, path, "Excluded (another filesystem)"); + return 1; + } + } } return 0; } int scanfd( - const client_conn_t *conn, - unsigned long int *scanned, - const struct cl_engine *engine, - struct cl_scan_options *options, - const struct optstruct *opts, - int odesc, - int stream) + const client_conn_t *conn, + unsigned long int *scanned, + const struct cl_engine *engine, + struct cl_scan_options *options, + const struct optstruct *opts, + int odesc, + int stream) { int ret, fd = conn->scanfd; - const char *virname = NULL; - STATBUF statbuf; - struct cb_context context; - char fdstr[32]; - const char*reply_fdstr; + const char *virname = NULL; + STATBUF statbuf; + struct cb_context context; + char fdstr[32]; + const char *reply_fdstr; UNUSEDPARAM(odesc); - if (stream) { - struct sockaddr_in sa; - socklen_t salen = sizeof(sa); - if(getpeername(conn->sd, (struct sockaddr *)&sa, &salen) || salen > sizeof(sa) || sa.sin_family != AF_INET) - strncpy(fdstr, "instream(local)", sizeof(fdstr)); - else - snprintf(fdstr, sizeof(fdstr), "instream(%s@%u)", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); - reply_fdstr = "stream"; - } else { - snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd); - reply_fdstr = fdstr; - } - if(FSTAT(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) { - logg("%s: Not a regular file. ERROR\n", fdstr); - if (conn_reply(conn, reply_fdstr, "Not a regular file", "ERROR") == -1) - return CL_ETIMEOUT; - return -1; - } - - thrmgr_setactivetask(fdstr, NULL); - context.filename = fdstr; - context.virsize = 0; - context.scandata = NULL; - ret = cl_scandesc_callback(fd, conn->filename, &virname, scanned, engine, options, &context); - thrmgr_setactivetask(NULL, NULL); - - if (thrmgr_group_need_terminate(conn->group)) { - logg("*Client disconnected while scanjob was active\n"); - return ret == CL_ETIMEOUT ? ret : CL_BREAK; - } - - if(ret == CL_VIRUS) { - if (conn_reply_virus(conn, reply_fdstr, virname) == -1) - ret = CL_ETIMEOUT; - if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) - logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize); - else - logg("%s: %s FOUND\n", fdstr, virname); - virusaction(reply_fdstr, virname, opts); - } else if(ret != CL_CLEAN) { - if (conn_reply(conn, reply_fdstr, cl_strerror(ret), "ERROR") == -1) - ret = CL_ETIMEOUT; - logg("%s: %s ERROR\n", fdstr, cl_strerror(ret)); - } else { - if (conn_reply_single(conn, reply_fdstr, "OK") == CL_ETIMEOUT) - ret = CL_ETIMEOUT; - if(logok) - logg("%s: OK\n", fdstr); - } - return ret; + if (stream) { + struct sockaddr_in sa; + socklen_t salen = sizeof(sa); + if (getpeername(conn->sd, (struct sockaddr *)&sa, &salen) || salen > sizeof(sa) || sa.sin_family != AF_INET) + strncpy(fdstr, "instream(local)", sizeof(fdstr)); + else + snprintf(fdstr, sizeof(fdstr), "instream(%s@%u)", inet_ntoa(sa.sin_addr), ntohs(sa.sin_port)); + reply_fdstr = "stream"; + } else { + snprintf(fdstr, sizeof(fdstr), "fd[%d]", fd); + reply_fdstr = fdstr; + } + if (FSTAT(fd, &statbuf) == -1 || !S_ISREG(statbuf.st_mode)) { + logg("%s: Not a regular file. ERROR\n", fdstr); + if (conn_reply(conn, reply_fdstr, "Not a regular file", "ERROR") == -1) + return CL_ETIMEOUT; + return -1; + } + + thrmgr_setactivetask(fdstr, NULL); + context.filename = fdstr; + context.virsize = 0; + context.scandata = NULL; + ret = cl_scandesc_callback(fd, NULL, &virname, scanned, engine, options, &context); + thrmgr_setactivetask(NULL, NULL); + + if (thrmgr_group_need_terminate(conn->group)) { + logg("*Client disconnected while scanjob was active\n"); + return ret == CL_ETIMEOUT ? ret : CL_BREAK; + } + + if (ret == CL_VIRUS) { + if (conn_reply_virus(conn, reply_fdstr, virname) == -1) + ret = CL_ETIMEOUT; + if (context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) + logg("%s: %s(%s:%llu) FOUND\n", fdstr, virname, context.virhash, context.virsize); + else + logg("%s: %s FOUND\n", fdstr, virname); + virusaction(reply_fdstr, virname, opts); + } else if (ret != CL_CLEAN) { + if (conn_reply(conn, reply_fdstr, cl_strerror(ret), "ERROR") == -1) + ret = CL_ETIMEOUT; + logg("%s: %s ERROR\n", fdstr, cl_strerror(ret)); + } else { + if (conn_reply_single(conn, reply_fdstr, "OK") == CL_ETIMEOUT) + ret = CL_ETIMEOUT; + if (logok) + logg("%s: OK\n", fdstr); + } + return ret; } int scanstream( - int odesc, - unsigned long int *scanned, - const struct cl_engine *engine, - struct cl_scan_options *options, - const struct optstruct *opts, - char term) + int odesc, + unsigned long int *scanned, + const struct cl_engine *engine, + struct cl_scan_options *options, + const struct optstruct *opts, + char term) { - int ret, sockfd, acceptd; - int tmpd, bread, retval, firsttimeout, timeout, btread; - unsigned int port = 0, portscan, min_port, max_port; - unsigned long int quota = 0, maxsize = 0; - short bound = 0; - const char *virname = NULL; - char buff[FILEBUFF]; - char peer_addr[32]; - struct cb_context context; - struct sockaddr_in server; - struct sockaddr_in peer; - socklen_t addrlen; - char *tmpname; - + int ret, sockfd, acceptd; + int tmpd, bread, retval, firsttimeout, timeout, btread; + unsigned int port = 0, portscan, min_port, max_port; + unsigned long int quota = 0, maxsize = 0; + short bound = 0; + const char *virname = NULL; + char buff[FILEBUFF]; + char peer_addr[32]; + struct cb_context context; + struct sockaddr_in server; + struct sockaddr_in peer; + socklen_t addrlen; + char *tmpname; min_port = optget(opts, "StreamMinPort")->numarg; max_port = optget(opts, "StreamMaxPort")->numarg; /* search for a free port to bind to */ - port = cli_rndnum(max_port - min_port); + port = cli_rndnum(max_port - min_port); bound = 0; for (portscan = 0; portscan < 1000; portscan++) { - port = (port - 1) % (max_port - min_port + 1); + port = (port - 1) % (max_port - min_port + 1); - memset((char *) &server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(min_port + port); - server.sin_addr.s_addr = htonl(INADDR_ANY); - - if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) - continue; - - if(bind(sockfd, (struct sockaddr *) &server, (socklen_t)sizeof(struct sockaddr_in)) == -1) - closesocket(sockfd); - else { - bound = 1; - break; - } + memset((char *)&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(min_port + port); + server.sin_addr.s_addr = htonl(INADDR_ANY); + + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + continue; + + if (bind(sockfd, (struct sockaddr *)&server, (socklen_t)sizeof(struct sockaddr_in)) == -1) + closesocket(sockfd); + else { + bound = 1; + break; + } } port += min_port; - timeout = optget(opts, "ReadTimeout")->numarg; + timeout = optget(opts, "ReadTimeout")->numarg; firsttimeout = optget(opts, "CommandReadTimeout")->numarg; - if(!bound) { - logg("!ScanStream: Can't find any free port.\n"); - mdprintf(odesc, "Can't find any free port. ERROR%c", term); - return -1; - } else { - if (listen(sockfd, 1) == -1) { - logg("!ScanStream: listen() error on socket. Error returned is %s.\n", strerror(errno)); - closesocket(sockfd); + if (!bound) { + logg("!ScanStream: Can't find any free port.\n"); + mdprintf(odesc, "Can't find any free port. ERROR%c", term); return -1; - } - if(mdprintf(odesc, "PORT %u%c", port, term) <= 0) { - logg("!ScanStream: error transmitting port.\n"); - closesocket(sockfd); - return -1; - } + } else { + if (listen(sockfd, 1) == -1) { + logg("!ScanStream: listen() error on socket. Error returned is %s.\n", strerror(errno)); + closesocket(sockfd); + return -1; + } + if (mdprintf(odesc, "PORT %u%c", port, term) <= 0) { + logg("!ScanStream: error transmitting port.\n"); + closesocket(sockfd); + return -1; + } } retval = poll_fd(sockfd, firsttimeout, 0); if (!retval || retval == -1) { - const char *reason = !retval ? "timeout" : "poll"; - mdprintf(odesc, "Accept %s. ERROR%c", reason, term); - logg("!ScanStream %u: accept %s.\n", port, reason); - closesocket(sockfd); - return -1; + const char *reason = !retval ? "timeout" : "poll"; + mdprintf(odesc, "Accept %s. ERROR%c", reason, term); + logg("!ScanStream %u: accept %s.\n", port, reason); + closesocket(sockfd); + return -1; } addrlen = sizeof(peer); - if((acceptd = accept(sockfd, (struct sockaddr *) &peer, (socklen_t *)&addrlen)) == -1) { - closesocket(sockfd); - mdprintf(odesc, "accept() ERROR%c", term); - logg("!ScanStream %u: accept() failed.\n", port); - return -1; + if ((acceptd = accept(sockfd, (struct sockaddr *)&peer, (socklen_t *)&addrlen)) == -1) { + closesocket(sockfd); + mdprintf(odesc, "accept() ERROR%c", term); + logg("!ScanStream %u: accept() failed.\n", port); + return -1; } *peer_addr = '\0'; inet_ntop(peer.sin_family, &peer.sin_addr, peer_addr, sizeof(peer_addr)); logg("*Accepted connection from %s on port %u, fd %d\n", peer_addr, port, acceptd); - if(cli_gentempfd(optget(opts, "TemporaryDirectory")->strarg, &tmpname, &tmpd)) { - shutdown(sockfd, 2); - closesocket(sockfd); - closesocket(acceptd); - mdprintf(odesc, "cli_gentempfd() failed. ERROR%c", term); - logg("!ScanStream(%s@%u): Can't create temporary file.\n", peer_addr, port); - return -1; + if (cli_gentempfd(optget(opts, "TemporaryDirectory")->strarg, &tmpname, &tmpd)) { + shutdown(sockfd, 2); + closesocket(sockfd); + closesocket(acceptd); + mdprintf(odesc, "cli_gentempfd() failed. ERROR%c", term); + logg("!ScanStream(%s@%u): Can't create temporary file.\n", peer_addr, port); + return -1; } quota = maxsize = optget(opts, "StreamMaxLength")->numarg; - while((retval = poll_fd(acceptd, timeout, 0)) == 1) { - /* only read up to max */ - btread = (maxsize && (quota < sizeof(buff))) ? quota : sizeof(buff); - if (!btread) { - logg("^ScanStream(%s@%u): Size limit reached (max: %lu)\n", peer_addr, port, maxsize); - break; /* Scan what we have */ - } - bread = recv(acceptd, buff, btread, 0); - if(bread <= 0) - break; - - quota -= bread; - - if(writen(tmpd, buff, bread) != bread) { - shutdown(sockfd, 2); - closesocket(sockfd); - closesocket(acceptd); - mdprintf(odesc, "Temporary file -> write ERROR%c", term); - logg("!ScanStream(%s@%u): Can't write to temporary file.\n", peer_addr, port); - close(tmpd); - if(!optget(opts, "LeaveTemporaryFiles")->enabled) - unlink(tmpname); - free(tmpname); - return -1; - } - } - - switch(retval) { - case 0: /* timeout */ - mdprintf(odesc, "read timeout ERROR%c", term); - logg("!ScanStream(%s@%u): read timeout.\n", peer_addr, port); - break; - case -1: - mdprintf(odesc, "read poll ERROR%c", term); - logg("!ScanStream(%s@%u): read poll failed.\n", peer_addr, port); - break; - } - - if(retval == 1) { - lseek(tmpd, 0, SEEK_SET); - thrmgr_setactivetask(peer_addr, NULL); - context.filename = peer_addr; - context.virsize = 0; - context.scandata = NULL; - ret = cl_scandesc_callback(tmpd, tmpname, &virname, scanned, engine, options, &context); - thrmgr_setactivetask(NULL, NULL); + while ((retval = poll_fd(acceptd, timeout, 0)) == 1) { + /* only read up to max */ + btread = (maxsize && (quota < sizeof(buff))) ? quota : sizeof(buff); + if (!btread) { + logg("^ScanStream(%s@%u): Size limit reached (max: %lu)\n", peer_addr, port, maxsize); + break; /* Scan what we have */ + } + bread = recv(acceptd, buff, btread, 0); + if (bread <= 0) + break; + + quota -= bread; + + if (writen(tmpd, buff, bread) != bread) { + shutdown(sockfd, 2); + closesocket(sockfd); + closesocket(acceptd); + mdprintf(odesc, "Temporary file -> write ERROR%c", term); + logg("!ScanStream(%s@%u): Can't write to temporary file.\n", peer_addr, port); + close(tmpd); + if (!optget(opts, "LeaveTemporaryFiles")->enabled) + unlink(tmpname); + free(tmpname); + return -1; + } + } + + switch (retval) { + case 0: /* timeout */ + mdprintf(odesc, "read timeout ERROR%c", term); + logg("!ScanStream(%s@%u): read timeout.\n", peer_addr, port); + break; + case -1: + mdprintf(odesc, "read poll ERROR%c", term); + logg("!ScanStream(%s@%u): read poll failed.\n", peer_addr, port); + break; + } + + if (retval == 1) { + lseek(tmpd, 0, SEEK_SET); + thrmgr_setactivetask(peer_addr, NULL); + context.filename = peer_addr; + context.virsize = 0; + context.scandata = NULL; + ret = cl_scandesc_callback(tmpd, NULL, &virname, scanned, engine, options, &context); + thrmgr_setactivetask(NULL, NULL); } else { - ret = -1; + ret = -1; } close(tmpd); - if(!optget(opts, "LeaveTemporaryFiles")->enabled) - unlink(tmpname); + if (!optget(opts, "LeaveTemporaryFiles")->enabled) + unlink(tmpname); free(tmpname); closesocket(acceptd); closesocket(sockfd); - if(ret == CL_VIRUS) { - if(context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) { - mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term); - logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize); - } else { - mdprintf(odesc, "stream: %s FOUND%c", virname, term); - logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname); - } - virusaction("stream", virname, opts); - } else if(ret != CL_CLEAN) { - if(retval == 1) { - mdprintf(odesc, "stream: %s ERROR%c", cl_strerror(ret), term); - logg("stream(%s@%u): %s ERROR\n", peer_addr, port, cl_strerror(ret)); - } + if (ret == CL_VIRUS) { + if (context.virsize && optget(opts, "ExtendedDetectionInfo")->enabled) { + mdprintf(odesc, "stream: %s(%s:%llu) FOUND%c", virname, context.virhash, context.virsize, term); + logg("stream(%s@%u): %s(%s:%llu) FOUND\n", peer_addr, port, virname, context.virhash, context.virsize); + } else { + mdprintf(odesc, "stream: %s FOUND%c", virname, term); + logg("stream(%s@%u): %s FOUND\n", peer_addr, port, virname); + } + virusaction("stream", virname, opts); + } else if (ret != CL_CLEAN) { + if (retval == 1) { + mdprintf(odesc, "stream: %s ERROR%c", cl_strerror(ret), term); + logg("stream(%s@%u): %s ERROR\n", peer_addr, port, cl_strerror(ret)); + } } else { - mdprintf(odesc, "stream: OK%c", term); - if(logok) - logg("stream(%s@%u): OK\n", peer_addr, port); + mdprintf(odesc, "stream: OK%c", term); + if (logok) + logg("stream(%s@%u): OK\n", peer_addr, port); } return ret; diff -Nru clamav-0.101.4+dfsg/clamd/scanner.h clamav-0.102.1+dfsg/clamd/scanner.h --- clamav-0.101.4+dfsg/clamd/scanner.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/scanner.h 2019-11-20 04:42:24.000000000 +0000 @@ -30,7 +30,10 @@ #include "thrmgr.h" #include "session.h" -enum scan_type { TYPE_INIT = -1, TYPE_SCAN = 0, TYPE_CONTSCAN = 1, TYPE_MULTISCAN = 2 }; +enum scan_type { TYPE_INIT = -1, + TYPE_SCAN = 0, + TYPE_CONTSCAN = 1, + TYPE_MULTISCAN = 2 }; struct scan_cb_data { int scantype; diff -Nru clamav-0.101.4+dfsg/clamd/server-th.c clamav-0.102.1+dfsg/clamd/server-th.c --- clamav-0.101.4+dfsg/clamd/server-th.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/server-th.c 2019-11-20 04:42:24.000000000 +0000 @@ -31,13 +31,13 @@ #include #include #include -#ifndef _WIN32 +#ifndef _WIN32 #include #include #include #include #endif -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif @@ -53,7 +53,6 @@ #include "shared/idmef_logging.h" -#include "onaccess_fan.h" #include "server.h" #include "thrmgr.h" #include "session.h" @@ -64,28 +63,28 @@ #define BUFFSIZE 1024 -int progexit = 0; -pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; -int reload = 0; -time_t reloaded_time = 0; +int progexit = 0; +pthread_mutex_t exit_mutex = PTHREAD_MUTEX_INITIALIZER; +int reload = 0; +time_t reloaded_time = 0; pthread_mutex_t reload_mutex = PTHREAD_MUTEX_INITIALIZER; -int sighup = 0; +int sighup = 0; extern pthread_mutex_t logg_mutex; static struct cl_stat dbstat; -void *event_wake_recv = NULL; +void *event_wake_recv = NULL; void *event_wake_accept = NULL; static void scanner_thread(void *arg) { - client_conn_t *conn = (client_conn_t *) arg; -#ifndef _WIN32 - sigset_t sigset; + client_conn_t *conn = (client_conn_t *)arg; +#ifndef _WIN32 + sigset_t sigset; #endif - int ret; - int virus=0, errors = 0; + int ret; + int virus = 0, errors = 0; -#ifndef _WIN32 +#ifndef _WIN32 /* ignore all signals */ sigfillset(&sigset); /* The behavior of a process is undefined after it ignores a @@ -103,24 +102,23 @@ ret = command(conn, &virus); if (ret == -1) { - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - errors = 1; + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + errors = 1; } else - errors = ret; + errors = ret; thrmgr_setactiveengine(NULL); if (conn->filename) - free(conn->filename); + free(conn->filename); logg("$Finished scanthread\n"); - if (thrmgr_group_finished(conn->group, virus ? EXIT_OTHER : - errors ? EXIT_ERROR : EXIT_OK)) { - logg("$Scanthread: connection shut down (FD %d)\n", conn->sd); - /* close connection if we were last in group */ - shutdown(conn->sd, 2); - closesocket(conn->sd); + if (thrmgr_group_finished(conn->group, virus ? EXIT_OTHER : errors ? EXIT_ERROR : EXIT_OK)) { + logg("$Scanthread: connection shut down (FD %d)\n", conn->sd); + /* close connection if we were last in group */ + shutdown(conn->sd, 2); + closesocket(conn->sd); } cl_engine_free(conn->engine); free(conn); @@ -132,114 +130,114 @@ void sighandler_th(int sig) { int action = 0; - switch(sig) { - case SIGINT: - case SIGTERM: - progexit = 1; - action = 1; - break; - -#ifdef SIGHUP - case SIGHUP: - sighup = 1; - action = 1; - break; -#endif - -#ifdef SIGUSR2 - case SIGUSR2: - reload = 1; - action = 1; - break; + switch (sig) { + case SIGINT: + case SIGTERM: + progexit = 1; + action = 1; + break; + +#ifdef SIGHUP + case SIGHUP: + sighup = 1; + action = 1; + break; +#endif + +#ifdef SIGUSR2 + case SIGUSR2: + reload = 1; + action = 1; + break; #endif - default: - break; /* Take no action on other signals - e.g. SIGPIPE */ + default: + break; /* Take no action on other signals - e.g. SIGPIPE */ } /* a signal doesn't always wake poll(), for example on FreeBSD */ if (action && syncpipe_wake_recv_w != -1) - if (write(syncpipe_wake_recv_w, "", 1) != 1) - logg("$Failed to write to syncpipe\n"); + if (write(syncpipe_wake_recv_w, "", 1) != 1) + logg("$Failed to write to syncpipe\n"); } static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts, int do_check, int *ret) { - const char *dbdir; - int retval; - unsigned int sigs = 0; - struct cl_settings *settings = NULL; + const char *dbdir; + int retval; + unsigned int sigs = 0; + struct cl_settings *settings = NULL; *ret = 0; - if(do_check) { - if(!dbstat.entries) { - logg("No stats for Database check - forcing reload\n"); - return engine; - } - - if(cl_statchkdir(&dbstat) == 1) { - logg("SelfCheck: Database modification detected. Forcing reload.\n"); - return engine; - } else { - logg("SelfCheck: Database status OK.\n"); - return NULL; - } + if (do_check) { + if (!dbstat.entries) { + logg("No stats for Database check - forcing reload\n"); + return engine; + } + + if (cl_statchkdir(&dbstat) == 1) { + logg("SelfCheck: Database modification detected. Forcing reload.\n"); + return engine; + } else { + logg("SelfCheck: Database status OK.\n"); + return NULL; + } } /* release old structure */ - if(engine) { - /* copy current settings */ - settings = cl_engine_settings_copy(engine); - if(!settings) - logg("^Can't make a copy of the current engine settings\n"); + if (engine) { + /* copy current settings */ + settings = cl_engine_settings_copy(engine); + if (!settings) + logg("^Can't make a copy of the current engine settings\n"); - thrmgr_setactiveengine(NULL); - cl_engine_free(engine); + thrmgr_setactiveengine(NULL); + cl_engine_free(engine); } dbdir = optget(opts, "DatabaseDirectory")->strarg; logg("Reading databases from %s\n", dbdir); - if(dbstat.entries) - cl_statfree(&dbstat); + if (dbstat.entries) + cl_statfree(&dbstat); memset(&dbstat, 0, sizeof(struct cl_stat)); - if((retval = cl_statinidir(dbdir, &dbstat))) { - logg("!cl_statinidir() failed: %s\n", cl_strerror(retval)); - *ret = 1; - if(settings) - cl_engine_settings_free(settings); - return NULL; - } - - if(!(engine = cl_engine_new())) { - logg("!Can't initialize antivirus engine\n"); - *ret = 1; - if(settings) - cl_engine_settings_free(settings); - return NULL; - } - - if(settings) { - retval = cl_engine_settings_apply(engine, settings); - if(retval != CL_SUCCESS) { - logg("^Can't apply previous engine settings: %s\n", cl_strerror(retval)); - logg("^Using default engine settings\n"); - } - cl_engine_settings_free(settings); - } - - if((retval = cl_load(dbdir, engine, &sigs, dboptions))) { - logg("!reload db failed: %s\n", cl_strerror(retval)); - cl_engine_free(engine); - *ret = 1; - return NULL; - } - - if((retval = cl_engine_compile(engine)) != 0) { - logg("!Database initialization error: can't compile engine: %s\n", cl_strerror(retval)); - cl_engine_free(engine); - *ret = 1; - return NULL; + if ((retval = cl_statinidir(dbdir, &dbstat))) { + logg("!cl_statinidir() failed: %s\n", cl_strerror(retval)); + *ret = 1; + if (settings) + cl_engine_settings_free(settings); + return NULL; + } + + if (!(engine = cl_engine_new())) { + logg("!Can't initialize antivirus engine\n"); + *ret = 1; + if (settings) + cl_engine_settings_free(settings); + return NULL; + } + + if (settings) { + retval = cl_engine_settings_apply(engine, settings); + if (retval != CL_SUCCESS) { + logg("^Can't apply previous engine settings: %s\n", cl_strerror(retval)); + logg("^Using default engine settings\n"); + } + cl_engine_settings_free(settings); + } + + if ((retval = cl_load(dbdir, engine, &sigs, dboptions))) { + logg("!reload db failed: %s\n", cl_strerror(retval)); + cl_engine_free(engine); + *ret = 1; + return NULL; + } + + if ((retval = cl_engine_compile(engine)) != 0) { + logg("!Database initialization error: can't compile engine: %s\n", cl_strerror(retval)); + cl_engine_free(engine); + *ret = 1; + return NULL; } logg("Database correctly reloaded (%u signatures)\n", sigs); @@ -257,55 +255,55 @@ { char *pos; if (!buf->off || off >= buf->off) { - *len = 0; - return NULL; + *len = 0; + return NULL; } *term = '\n'; switch (buf->buffer[off]) { - /* commands terminated by delimiters */ - case 'z': - *term = '\0'; - case 'n': - pos = memchr(buf->buffer + off, *term, buf->off - off); - if (!pos) { - /* we don't have another full command yet */ - *len = 0; - return NULL; - } - *pos = '\0'; - if (*term) { - *len = cli_chomp(buf->buffer + off); - } else { - *len = pos - buf->buffer - off; - } - *oldstyle = 0; - return buf->buffer + off + 1; - default: - /* one packet = one command */ - if (off) - return NULL; - pos = memchr(buf->buffer, '\n', buf->off); - if (pos) { - *len = pos - buf->buffer; - *pos = '\0'; - } else { - *len = buf->off; - buf->buffer[buf->off] = '\0'; - } - cli_chomp(buf->buffer); - *oldstyle = 1; - return buf->buffer; + /* commands terminated by delimiters */ + case 'z': + *term = '\0'; + case 'n': + pos = memchr(buf->buffer + off, *term, buf->off - off); + if (!pos) { + /* we don't have another full command yet */ + *len = 0; + return NULL; + } + *pos = '\0'; + if (*term) { + *len = cli_chomp(buf->buffer + off); + } else { + *len = pos - buf->buffer - off; + } + *oldstyle = 0; + return buf->buffer + off + 1; + default: + /* one packet = one command */ + if (off) + return NULL; + pos = memchr(buf->buffer, '\n', buf->off); + if (pos) { + *len = pos - buf->buffer; + *pos = '\0'; + } else { + *len = buf->off; + buf->buffer[buf->off] = '\0'; + } + cli_chomp(buf->buffer); + *oldstyle = 1; + return buf->buffer; } } -int statinidir_th(const char* dirname) +int statinidir_th(const char *dirname) { - if (!dbstat.entries) { - memset(&dbstat, 0, sizeof(dbstat)); - } + if (!dbstat.entries) { + memset(&dbstat, 0, sizeof(dbstat)); + } - return cl_statinidir(dirname, &dbstat); + return cl_statinidir(dirname, &dbstat); } struct acceptdata { @@ -318,150 +316,148 @@ int syncpipe_wake_accept[2]; }; -#define ACCEPTDATA_INIT(mutex1, mutex2) { FDS_INIT(mutex1), FDS_INIT(mutex2), PTHREAD_COND_INITIALIZER, 0, 0, {-1, -1}, {-1, -1}} +#define ACCEPTDATA_INIT(mutex1, mutex2) \ + { \ + FDS_INIT(mutex1), FDS_INIT(mutex2), PTHREAD_COND_INITIALIZER, 0, 0, {-1, -1}, \ + { \ + -1, -1 \ + } \ + } static void *acceptloop_th(void *arg) { char buff[BUFFSIZE + 1]; size_t i; - struct acceptdata *data = (struct acceptdata*)arg; - struct fd_data *fds = &data->fds; + struct acceptdata *data = (struct acceptdata *)arg; + struct fd_data *fds = &data->fds; struct fd_data *recv_fds = &data->recv_fds; - int max_queue = data->max_queue; - int commandtimeout = data->commandtimeout; + int max_queue = data->max_queue; + int commandtimeout = data->commandtimeout; pthread_mutex_lock(fds->buf_mutex); for (;;) { - /* Block waiting for data to become available for reading */ - int new_sd = fds_poll_recv(fds, -1, 0, event_wake_accept); + /* Block waiting for data to become available for reading */ + int new_sd = fds_poll_recv(fds, -1, 0, event_wake_accept); #ifdef _WIN32 - ResetEvent(event_wake_accept); + ResetEvent(event_wake_accept); #endif - /* TODO: what about sockets that get rm-ed? */ - if (!fds->nfds) { - /* no more sockets to poll, all gave an error */ - logg("!Main socket gone: fatal\n"); - break; - } - - if (new_sd == -1 && errno != EINTR) { - logg("!Failed to poll sockets, fatal\n"); - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - break; - } - - /* accept() loop */ - for (i=0;i < fds->nfds && new_sd >= 0; i++) { - struct fd_buf *buf = &fds->buf[i]; - if (!buf->got_newdata) - continue; + /* TODO: what about sockets that get rm-ed? */ + if (!fds->nfds) { + /* no more sockets to poll, all gave an error */ + logg("!Main socket gone: fatal\n"); + break; + } + + if (new_sd == -1 && errno != EINTR) { + logg("!Failed to poll sockets, fatal\n"); + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + break; + } + + /* accept() loop */ + for (i = 0; i < fds->nfds && new_sd >= 0; i++) { + struct fd_buf *buf = &fds->buf[i]; + if (!buf->got_newdata) + continue; #ifndef _WIN32 - if (buf->fd == data->syncpipe_wake_accept[0]) { - /* dummy sync pipe, just to wake us */ - if (read(buf->fd, buff, sizeof(buff)) < 0) { - logg("^Syncpipe read failed\n"); - } - continue; - } -#endif - if (buf->got_newdata == -1) { - logg("$Acceptloop closed FD: %d\n", buf->fd); - shutdown(buf->fd, 2); - closesocket(buf->fd); - buf->fd = -1; - continue; - } - - /* don't accept unlimited number of connections, or - * we'll run out of file descriptors */ - pthread_mutex_lock(recv_fds->buf_mutex); - while (recv_fds->nfds > (unsigned)max_queue) { - pthread_mutex_lock(&exit_mutex); - if(progexit) { - pthread_mutex_unlock(&exit_mutex); - break; - } - pthread_mutex_unlock(&exit_mutex); - pthread_cond_wait(&data->cond_nfds, recv_fds->buf_mutex); - } - pthread_mutex_unlock(recv_fds->buf_mutex); - - pthread_mutex_lock(&exit_mutex); - if(progexit) { - pthread_mutex_unlock(&exit_mutex); - break; - } - pthread_mutex_unlock(&exit_mutex); + if (buf->fd == data->syncpipe_wake_accept[0]) { + /* dummy sync pipe, just to wake us */ + if (read(buf->fd, buff, sizeof(buff)) < 0) { + logg("^Syncpipe read failed\n"); + } + continue; + } +#endif + if (buf->got_newdata == -1) { + logg("$Acceptloop closed FD: %d\n", buf->fd); + shutdown(buf->fd, 2); + closesocket(buf->fd); + buf->fd = -1; + continue; + } - /* listen only socket */ - new_sd = accept(fds->buf[i].fd, NULL, NULL); + /* don't accept unlimited number of connections, or + * we'll run out of file descriptors */ + pthread_mutex_lock(recv_fds->buf_mutex); + while (recv_fds->nfds > (unsigned)max_queue) { + pthread_mutex_lock(&exit_mutex); + if (progexit) { + pthread_mutex_unlock(&exit_mutex); + break; + } + pthread_mutex_unlock(&exit_mutex); + pthread_cond_wait(&data->cond_nfds, recv_fds->buf_mutex); + } + pthread_mutex_unlock(recv_fds->buf_mutex); - if (new_sd >= 0) { - int ret, flags; + pthread_mutex_lock(&exit_mutex); + if (progexit) { + pthread_mutex_unlock(&exit_mutex); + break; + } + pthread_mutex_unlock(&exit_mutex); + + /* listen only socket */ + new_sd = accept(fds->buf[i].fd, NULL, NULL); + + if (new_sd >= 0) { + int ret, flags; #ifdef F_GETFL - flags = fcntl(new_sd, F_GETFL, 0); - if (flags != -1) { - if (fcntl(new_sd, F_SETFL, flags | O_NONBLOCK) == -1) { - logg("^Can't set socket to nonblocking mode, errno %d\n", - errno); - } - } else { - logg("^Can't get socket flags, errno %d\n", errno); - } + flags = fcntl(new_sd, F_GETFL, 0); + if (flags != -1) { + if (fcntl(new_sd, F_SETFL, flags | O_NONBLOCK) == -1) { + logg("^Can't set socket to nonblocking mode, errno %d\n", + errno); + } + } else { + logg("^Can't get socket flags, errno %d\n", errno); + } #else - logg("^Nonblocking sockets not available!\n"); + logg("^Nonblocking sockets not available!\n"); #endif - logg("$Got new connection, FD %d\n", new_sd); - pthread_mutex_lock(recv_fds->buf_mutex); - ret = fds_add(recv_fds, new_sd, 0, commandtimeout); - pthread_mutex_unlock(recv_fds->buf_mutex); - - if (ret == -1) { - logg("!fds_add failed\n"); - closesocket(new_sd); - continue; - } + logg("$Got new connection, FD %d\n", new_sd); + pthread_mutex_lock(recv_fds->buf_mutex); + ret = fds_add(recv_fds, new_sd, 0, commandtimeout); + pthread_mutex_unlock(recv_fds->buf_mutex); + + if (ret == -1) { + logg("!fds_add failed\n"); + closesocket(new_sd); + continue; + } - /* notify recvloop */ + /* notify recvloop */ #ifdef _WIN32 - SetEvent(event_wake_recv); -#else - if (write(data->syncpipe_wake_recv[1], "", 1) == -1) { - logg("!write syncpipe failed\n"); - continue; - } -#endif - } else if (errno != EINTR) { - /* very bad - need to exit or restart */ -#ifdef HAVE_STRERROR_R - (void)strerror_r(errno, buff, BUFFSIZE); - logg("!accept() failed: %s\n", buff); + SetEvent(event_wake_recv); #else - logg("!accept() failed\n"); + if (write(data->syncpipe_wake_recv[1], "", 1) == -1) { + logg("!write syncpipe failed\n"); + continue; + } #endif - /* give the poll loop a chance to close disconnected FDs */ - break; - } - - } - - /* handle progexit */ - pthread_mutex_lock(&exit_mutex); - if (progexit) { - pthread_mutex_unlock(&exit_mutex); - break; - } - pthread_mutex_unlock(&exit_mutex); + } else if (errno != EINTR) { + /* very bad - need to exit or restart */ + logg("!accept() failed: %s\n", cli_strerror(errno, buff, BUFFSIZE)); + /* give the poll loop a chance to close disconnected FDs */ + break; + } + } + + /* handle progexit */ + pthread_mutex_lock(&exit_mutex); + if (progexit) { + pthread_mutex_unlock(&exit_mutex); + break; + } + pthread_mutex_unlock(&exit_mutex); } pthread_mutex_unlock(fds->buf_mutex); - if (sd_listen_fds(0) == 0) - { + if (sd_listen_fds(0) == 0) { /* only close the sockets, when not using systemd socket activation */ - for (i=0;i < fds->nfds; i++) - { + for (i = 0; i < fds->nfds; i++) { if (fds->buf[i].fd == -1) continue; logg("$Shutdown: closed fd %d\n", fds->buf[i].fd); @@ -479,13 +475,13 @@ SetEvent(event_wake_recv); #else if (write(data->syncpipe_wake_recv[1], "", 1) < 0) { - logg("$Syncpipe write failed\n"); + logg("$Syncpipe write failed\n"); } #endif return NULL; } -static const char* parse_dispatch_cmd(client_conn_t *conn, struct fd_buf *buf, size_t *ppos, int *error, const struct optstruct *opts, int readtimeout) +static const char *parse_dispatch_cmd(client_conn_t *conn, struct fd_buf *buf, size_t *ppos, int *error, const struct optstruct *opts, int readtimeout) { const char *cmd = NULL; int rc; @@ -495,131 +491,131 @@ size_t pos = *ppos; /* Parse & dispatch commands */ while ((conn->mode == MODE_COMMAND) && - (cmd = get_cmd(buf, pos, &cmdlen, &term, &oldstyle)) != NULL) { - const char *argument; - enum commands cmdtype; - if (conn->group && oldstyle) { - logg("$Received oldstyle command inside IDSESSION: %s\n", cmd); - conn_reply_error(conn, "Only nCMDS\\n and zCMDS\\0 are accepted inside IDSESSION."); - *error = 1; - break; - } - cmdtype = parse_command(cmd, &argument, oldstyle); - logg("$got command %s (%u, %u), argument: %s\n", - cmd, (unsigned)cmdlen, (unsigned)cmdtype, argument ? argument : ""); - if (cmdtype == COMMAND_FILDES) { - if (buf->buffer + buf->off <= cmd + strlen("FILDES\n")) { - /* we need the extra byte from recvmsg */ - conn->mode = MODE_WAITANCILL; - buf->mode = MODE_WAITANCILL; - /* put term back */ - buf->buffer[pos + cmdlen] = term; - cmdlen = 0; - logg("$RECVTH: mode -> MODE_WAITANCILL\n"); - break; - } - /* eat extra \0 for controlmsg */ - cmdlen++; - logg("$RECVTH: FILDES command complete\n"); - } - conn->term = term; - buf->term = term; - - if ((rc = execute_or_dispatch_command(conn, cmdtype, argument)) < 0) { - logg("!Command dispatch failed\n"); - if(rc == -1 && optget(opts, "ExitOnOOM")->enabled) { - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - } - *error = 1; - } - if (thrmgr_group_need_terminate(conn->group)) { - logg("$Receive thread: have to terminate group\n"); - *error = CL_ETIMEOUT; - break; - } - if (*error || !conn->group || rc) { - if (rc && thrmgr_group_finished(conn->group, EXIT_OK)) { - logg("$Receive thread: closing conn (FD %d), group finished\n", conn->sd); - /* if there are no more active jobs */ - shutdown(conn->sd, 2); - closesocket(conn->sd); - buf->fd = -1; - conn->group = NULL; - } else if (conn->mode != MODE_STREAM) { - logg("$mode -> MODE_WAITREPLY\n"); - /* no more commands are accepted */ - conn->mode = MODE_WAITREPLY; - /* Stop monitoring this FD, it will be closed either - * by us, or by the scanner thread. - * Never close a file descriptor that is being - * monitored by poll()/select() from another thread, - * because this can lead to subtle bugs such as: - * Other thread closes file descriptor -> POLLHUP is - * set, but the poller thread doesn't wake up yet. - * Another client opens a connection and sends some - * data. If the socket reuses the previous file descriptor, - * then POLLIN is set on the file descriptor too. - * When poll() wakes up it sees POLLIN | POLLHUP - * and thinks that the client has sent some data, - * and closed the connection, so clamd closes the - * connection in turn resulting in a bug. - * - * If we wouldn't have poll()-ed the file descriptor - * we closed in another thread, but rather made sure - * that we don't put a FD that we're about to close - * into poll()'s list of watched fds; then POLLHUP - * would be set, but the file descriptor would stay - * open, until we wake up from poll() and close it. - * Thus a new connection won't be able to reuse the - * same FD, and there is no bug. - * */ - buf->fd = -1; - } - } - /* we received a command, set readtimeout */ - time(&buf->timeout_at); - buf->timeout_at += readtimeout; - pos += cmdlen+1; - if (conn->mode == MODE_STREAM) { - /* TODO: this doesn't belong here */ - buf->dumpname = conn->filename; - buf->dumpfd = conn->scanfd; - logg("$Receive thread: INSTREAM: %s fd %u\n", buf->dumpname, buf->dumpfd); - } - if (conn->mode != MODE_COMMAND) { - logg("$Breaking command loop, mode is no longer MODE_COMMAND\n"); - break; - } - conn->id++; + (cmd = get_cmd(buf, pos, &cmdlen, &term, &oldstyle)) != NULL) { + const char *argument; + enum commands cmdtype; + if (conn->group && oldstyle) { + logg("$Received oldstyle command inside IDSESSION: %s\n", cmd); + conn_reply_error(conn, "Only nCMDS\\n and zCMDS\\0 are accepted inside IDSESSION."); + *error = 1; + break; + } + cmdtype = parse_command(cmd, &argument, oldstyle); + logg("$got command %s (%u, %u), argument: %s\n", + cmd, (unsigned)cmdlen, (unsigned)cmdtype, argument ? argument : ""); + if (cmdtype == COMMAND_FILDES) { + if (buf->buffer + buf->off <= cmd + strlen("FILDES\n")) { + /* we need the extra byte from recvmsg */ + conn->mode = MODE_WAITANCILL; + buf->mode = MODE_WAITANCILL; + /* put term back */ + buf->buffer[pos + cmdlen] = term; + cmdlen = 0; + logg("$RECVTH: mode -> MODE_WAITANCILL\n"); + break; + } + /* eat extra \0 for controlmsg */ + cmdlen++; + logg("$RECVTH: FILDES command complete\n"); + } + conn->term = term; + buf->term = term; + + if ((rc = execute_or_dispatch_command(conn, cmdtype, argument)) < 0) { + logg("!Command dispatch failed\n"); + if (rc == -1 && optget(opts, "ExitOnOOM")->enabled) { + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + } + *error = 1; + } + if (thrmgr_group_need_terminate(conn->group)) { + logg("$Receive thread: have to terminate group\n"); + *error = CL_ETIMEOUT; + break; + } + if (*error || !conn->group || rc) { + if (rc && thrmgr_group_finished(conn->group, EXIT_OK)) { + logg("$Receive thread: closing conn (FD %d), group finished\n", conn->sd); + /* if there are no more active jobs */ + shutdown(conn->sd, 2); + closesocket(conn->sd); + buf->fd = -1; + conn->group = NULL; + } else if (conn->mode != MODE_STREAM) { + logg("$mode -> MODE_WAITREPLY\n"); + /* no more commands are accepted */ + conn->mode = MODE_WAITREPLY; + /* Stop monitoring this FD, it will be closed either + * by us, or by the scanner thread. + * Never close a file descriptor that is being + * monitored by poll()/select() from another thread, + * because this can lead to subtle bugs such as: + * Other thread closes file descriptor -> POLLHUP is + * set, but the poller thread doesn't wake up yet. + * Another client opens a connection and sends some + * data. If the socket reuses the previous file descriptor, + * then POLLIN is set on the file descriptor too. + * When poll() wakes up it sees POLLIN | POLLHUP + * and thinks that the client has sent some data, + * and closed the connection, so clamd closes the + * connection in turn resulting in a bug. + * + * If we wouldn't have poll()-ed the file descriptor + * we closed in another thread, but rather made sure + * that we don't put a FD that we're about to close + * into poll()'s list of watched fds; then POLLHUP + * would be set, but the file descriptor would stay + * open, until we wake up from poll() and close it. + * Thus a new connection won't be able to reuse the + * same FD, and there is no bug. + */ + buf->fd = -1; + } + } + /* we received a command, set readtimeout */ + time(&buf->timeout_at); + buf->timeout_at += readtimeout; + pos += cmdlen + 1; + if (conn->mode == MODE_STREAM) { + /* TODO: this doesn't belong here */ + buf->dumpname = conn->filename; + buf->dumpfd = conn->scanfd; + logg("$Receive thread: INSTREAM: %s fd %u\n", buf->dumpname, buf->dumpfd); + } + if (conn->mode != MODE_COMMAND) { + logg("$Breaking command loop, mode is no longer MODE_COMMAND\n"); + break; + } + conn->id++; } - *ppos = pos; - buf->mode = conn->mode; - buf->id = conn->id; + *ppos = pos; + buf->mode = conn->mode; + buf->id = conn->id; buf->group = conn->group; buf->quota = conn->quota; if (conn->scanfd != -1 && conn->scanfd != buf->dumpfd) { - logg("$Unclaimed file descriptor received, closing: %d\n", conn->scanfd); - close(conn->scanfd); - /* protocol error */ - conn_reply_error(conn, "PROTOCOL ERROR: ancillary data sent without FILDES."); - *error = 1; - return NULL; + logg("$Unclaimed file descriptor received, closing: %d\n", conn->scanfd); + close(conn->scanfd); + /* protocol error */ + conn_reply_error(conn, "PROTOCOL ERROR: ancillary data sent without FILDES."); + *error = 1; + return NULL; } if (!*error) { - /* move partial command to beginning of buffer */ - if (pos < buf->off) { - memmove (buf->buffer, &buf->buffer[pos], buf->off - pos); - buf->off -= pos; - } else - buf->off = 0; - if (buf->off) - logg("$Moved partial command: %lu\n", (unsigned long)buf->off); - else - logg("$Consumed entire command\n"); - /* adjust pos to account for the buffer shuffle */ - pos = 0; + /* move partial command to beginning of buffer */ + if (pos < buf->off) { + memmove(buf->buffer, &buf->buffer[pos], buf->off - pos); + buf->off -= pos; + } else + buf->off = 0; + if (buf->off) + logg("$Moved partial command: %lu\n", (unsigned long)buf->off); + else + logg("$Consumed entire command\n"); + /* adjust pos to account for the buffer shuffle */ + pos = 0; } *ppos = pos; return cmd; @@ -637,78 +633,78 @@ time(&buf->timeout_at); buf->timeout_at += readtimeout; while (pos <= buf->off) { - if (!buf->chunksize) { - /* read chunksize */ - if (buf->off-pos >= 4) { - uint32_t cs; - memmove(&cs, buf->buffer + pos, 4); - pos += 4; - buf->chunksize = ntohl(cs); - logg("$Got chunksize: %u\n", buf->chunksize); - if (!buf->chunksize) { - /* chunksize 0 marks end of stream */ - conn->scanfd = buf->dumpfd; - conn->term = buf->term; - buf->dumpfd = -1; - buf->mode = buf->group ? MODE_COMMAND : MODE_WAITREPLY; - if (buf->mode == MODE_WAITREPLY) - buf->fd = -1; - logg("$Chunks complete\n"); - buf->dumpname = NULL; - if ((rc = execute_or_dispatch_command(conn, COMMAND_INSTREAMSCAN, NULL)) < 0) { - logg("!Command dispatch failed\n"); - if(rc == -1 && optget(opts, "ExitOnOOM")->enabled) { - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - } - *error = 1; - } else { - memmove (buf->buffer, &buf->buffer[pos], buf->off - pos); - buf->off -= pos; - *ppos = 0; - buf->id++; - return 0; + if (!buf->chunksize) { + /* read chunksize */ + if (buf->off - pos >= 4) { + uint32_t cs; + memmove(&cs, buf->buffer + pos, 4); + pos += 4; + buf->chunksize = ntohl(cs); + logg("$Got chunksize: %u\n", buf->chunksize); + if (!buf->chunksize) { + /* chunksize 0 marks end of stream */ + conn->scanfd = buf->dumpfd; + conn->term = buf->term; + buf->dumpfd = -1; + buf->mode = buf->group ? MODE_COMMAND : MODE_WAITREPLY; + if (buf->mode == MODE_WAITREPLY) + buf->fd = -1; + logg("$Chunks complete\n"); + buf->dumpname = NULL; + if ((rc = execute_or_dispatch_command(conn, COMMAND_INSTREAMSCAN, NULL)) < 0) { + logg("!Command dispatch failed\n"); + if (rc == -1 && optget(opts, "ExitOnOOM")->enabled) { + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + } + *error = 1; + } else { + memmove(buf->buffer, &buf->buffer[pos], buf->off - pos); + buf->off -= pos; + *ppos = 0; + buf->id++; + return 0; } - } - if (buf->chunksize > buf->quota) { - logg("^INSTREAM: Size limit reached, (requested: %lu, max: %lu)\n", - (unsigned long)buf->chunksize, (unsigned long)buf->quota); - conn_reply_error(conn, "INSTREAM size limit exceeded."); + } + if (buf->chunksize > buf->quota) { + logg("^INSTREAM: Size limit reached, (requested: %lu, max: %lu)\n", + (unsigned long)buf->chunksize, (unsigned long)buf->quota); + conn_reply_error(conn, "INSTREAM size limit exceeded."); *error = 1; - *ppos = pos; - return -1; + *ppos = pos; + return -1; } else { - buf->quota -= buf->chunksize; + buf->quota -= buf->chunksize; } - logg("$Quota Remaining: %lu\n", buf->quota); - } else { - /* need more data, so return and wait for some */ - memmove (buf->buffer, &buf->buffer[pos], buf->off - pos); - buf->off -= pos; - *ppos = 0; + logg("$Quota Remaining: %lu\n", buf->quota); + } else { + /* need more data, so return and wait for some */ + memmove(buf->buffer, &buf->buffer[pos], buf->off - pos); + buf->off -= pos; + *ppos = 0; return -1; } - } - if (pos + buf->chunksize < buf->off) - cmdlen = buf->chunksize; - else - cmdlen = buf->off - pos; - buf->chunksize -= cmdlen; - if (cli_writen(buf->dumpfd, buf->buffer + pos, cmdlen) < 0) { - conn_reply_error(conn, "Error writing to temporary file"); - logg("!INSTREAM: Can't write to temporary file.\n"); - *error = 1; - } - logg("$Processed %llu bytes of chunkdata, pos %llu\n", (long long unsigned)cmdlen, (long long unsigned)pos); - pos += cmdlen; - if (pos == buf->off) { - buf->off = 0; - pos = 0; - /* need more data, so return and wait for some */ - *ppos = pos; + } + if (pos + buf->chunksize < buf->off) + cmdlen = buf->chunksize; + else + cmdlen = buf->off - pos; + buf->chunksize -= cmdlen; + if (cli_writen(buf->dumpfd, buf->buffer + pos, cmdlen) == (size_t)-1) { + conn_reply_error(conn, "Error writing to temporary file"); + logg("!INSTREAM: Can't write to temporary file.\n"); + *error = 1; + } + logg("$Processed %llu bytes of chunkdata, pos %llu\n", (long long unsigned)cmdlen, (long long unsigned)pos); + pos += cmdlen; + if (pos == buf->off) { + buf->off = 0; + pos = 0; + /* need more data, so return and wait for some */ + *ppos = pos; return -1; - } + } } *ppos = pos; return 0; @@ -716,42 +712,36 @@ int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts) { - int max_threads, max_queue, readtimeout, ret = 0; - struct cl_scan_options options; - char timestr[32]; -#ifndef _WIN32 - struct sigaction sigact; - sigset_t sigset; - struct rlimit rlim; -#endif - mode_t old_umask; - const struct optstruct *opt; - char buff[BUFFSIZE + 1]; - pid_t mainpid; - int idletimeout; - unsigned long long val; - size_t i, j, rr_last = 0; - pthread_t accept_th; - pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER; - pthread_mutex_t recvfds_mutex = PTHREAD_MUTEX_INITIALIZER; - struct acceptdata acceptdata = ACCEPTDATA_INIT(&fds_mutex, &recvfds_mutex); - struct fd_data *fds = &acceptdata.recv_fds; - time_t start_time, current_time; - unsigned int selfchk; - threadpool_t *thr_pool; - -#if defined(FANOTIFY) || defined(CLAMAUTH) - pthread_t fan_pid = 0; - pthread_attr_t fan_attr; - struct thrarg *tharg = NULL; /* shut up gcc */ + int max_threads, max_queue, readtimeout, ret = 0; + struct cl_scan_options options; + char timestr[32]; +#ifndef _WIN32 + struct sigaction sigact; + sigset_t sigset; + struct rlimit rlim; #endif + mode_t old_umask; + const struct optstruct *opt; + char buff[BUFFSIZE + 1]; + pid_t mainpid; + int idletimeout; + unsigned long long val; + size_t i, j, rr_last = 0; + pthread_t accept_th; + pthread_mutex_t fds_mutex = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t recvfds_mutex = PTHREAD_MUTEX_INITIALIZER; + struct acceptdata acceptdata = ACCEPTDATA_INIT(&fds_mutex, &recvfds_mutex); + struct fd_data *fds = &acceptdata.recv_fds; + time_t start_time, current_time; + unsigned int selfchk; + threadpool_t *thr_pool; -#ifndef _WIN32 - memset(&sigact, 0, sizeof(struct sigaction)); +#ifndef _WIN32 + memset(&sigact, 0, sizeof(struct sigaction)); #endif - /* Initalize scan options struct */ - memset(&options, 0, sizeof(struct cl_scan_options)); + /* Initalize scan options struct */ + memset(&options, 0, sizeof(struct cl_scan_options)); /* set up limits */ if ((opt = optget(opts, "MaxScanTime"))->active) { @@ -775,71 +765,71 @@ } } val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL); - if(val) - logg("Limits: Global size limit set to %llu bytes.\n", val); + if (val) + logg("Limits: Global size limit set to %llu bytes.\n", val); else - logg("^Limits: Global size limit protection disabled.\n"); + logg("^Limits: Global size limit protection disabled.\n"); - if((opt = optget(opts, "MaxFileSize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) { - logg("!cl_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret)); - cl_engine_free(engine); - return 1; - } + if ((opt = optget(opts, "MaxFileSize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) { + logg("!cl_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret)); + cl_engine_free(engine); + return 1; + } } val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL); - if(val) - logg("Limits: File size limit set to %llu bytes.\n", val); + if (val) + logg("Limits: File size limit set to %llu bytes.\n", val); else - logg("^Limits: File size limit protection disabled.\n"); + logg("^Limits: File size limit protection disabled.\n"); #ifndef _WIN32 - if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) { - if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL)) - logg("^System limit for file size is lower than engine->maxfilesize\n"); - if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL)) - logg("^System limit for file size is lower than engine->maxscansize\n"); + if (getrlimit(RLIMIT_FSIZE, &rlim) == 0) { + if (rlim.rlim_cur < (rlim_t)cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL)) + logg("^System limit for file size is lower than engine->maxfilesize\n"); + if (rlim.rlim_cur < (rlim_t)cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL)) + logg("^System limit for file size is lower than engine->maxscansize\n"); } else { - logg("^Cannot obtain resource limits for file size\n"); + logg("^Cannot obtain resource limits for file size\n"); } #endif - if((opt = optget(opts, "MaxRecursion"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) { - logg("!cl_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret)); - cl_engine_free(engine); - return 1; - } + if ((opt = optget(opts, "MaxRecursion"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) { + logg("!cl_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret)); + cl_engine_free(engine); + return 1; + } } val = cl_engine_get_num(engine, CL_ENGINE_MAX_RECURSION, NULL); - if(val) - logg("Limits: Recursion level limit set to %u.\n", (unsigned int) val); + if (val) + logg("Limits: Recursion level limit set to %u.\n", (unsigned int)val); else - logg("^Limits: Recursion level limit protection disabled.\n"); + logg("^Limits: Recursion level limit protection disabled.\n"); - if((opt = optget(opts, "MaxFiles"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) { - logg("!cl_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret)); - cl_engine_free(engine); - return 1; - } + if ((opt = optget(opts, "MaxFiles"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) { + logg("!cl_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret)); + cl_engine_free(engine); + return 1; + } } val = cl_engine_get_num(engine, CL_ENGINE_MAX_FILES, NULL); - if(val) - logg("Limits: Files limit set to %u.\n", (unsigned int) val); + if (val) + logg("Limits: Files limit set to %u.\n", (unsigned int)val); else - logg("^Limits: Files limit protection disabled.\n"); + logg("^Limits: Files limit protection disabled.\n"); #ifndef _WIN32 if (getrlimit(RLIMIT_CORE, &rlim) == 0) { - logg("*Limits: Core-dump limit is %lu.\n", (unsigned long)rlim.rlim_cur); + logg("*Limits: Core-dump limit is %lu.\n", (unsigned long)rlim.rlim_cur); } #endif /* Engine max sizes */ - if((opt = optget(opts, "MaxEmbeddedPE"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) { + if ((opt = optget(opts, "MaxEmbeddedPE"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_EMBEDDEDPE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -848,8 +838,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, NULL); logg("Limits: MaxEmbeddedPE limit set to %llu bytes.\n", val); - if((opt = optget(opts, "MaxHTMLNormalize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) { + if ((opt = optget(opts, "MaxHTMLNormalize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNORMALIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -858,8 +848,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, NULL); logg("Limits: MaxHTMLNormalize limit set to %llu bytes.\n", val); - if((opt = optget(opts, "MaxHTMLNoTags"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) { + if ((opt = optget(opts, "MaxHTMLNoTags"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNOTAGS) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -868,8 +858,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, NULL); logg("Limits: MaxHTMLNoTags limit set to %llu bytes.\n", val); - if((opt = optget(opts, "MaxScriptNormalize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) { + if ((opt = optget(opts, "MaxScriptNormalize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_SCRIPTNORMALIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -878,8 +868,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, NULL); logg("Limits: MaxScriptNormalize limit set to %llu bytes.\n", val); - if((opt = optget(opts, "MaxZipTypeRcg"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) { + if ((opt = optget(opts, "MaxZipTypeRcg"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_ZIPTYPERCG) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -888,8 +878,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, NULL); logg("Limits: MaxZipTypeRcg limit set to %llu bytes.\n", val); - if((opt = optget(opts, "MaxPartitions"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) { + if ((opt = optget(opts, "MaxPartitions"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) { logg("!cli_engine_set_num(MaxPartitions) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -898,8 +888,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_PARTITIONS, NULL); logg("Limits: MaxPartitions limit set to %llu.\n", val); - if((opt = optget(opts, "MaxIconsPE"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) { + if ((opt = optget(opts, "MaxIconsPE"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) { logg("!cli_engine_set_num(MaxIconsPE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -908,8 +898,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_MAX_ICONSPE, NULL); logg("Limits: MaxIconsPE limit set to %llu.\n", val); - if((opt = optget(opts, "MaxRecHWP3"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECHWP3, opt->numarg))) { + if ((opt = optget(opts, "MaxRecHWP3"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECHWP3, opt->numarg))) { logg("!cli_engine_set_num(MaxRecHWP3) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -925,8 +915,8 @@ val = cl_engine_get_num(engine, CL_ENGINE_PCRE_RECMATCH_LIMIT, NULL); logg("Limits: PCRERecMatchLimit limit set to %llu.\n", val); - if((opt = optget(opts, "PCREMaxFileSize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, opt->numarg))) { + if ((opt = optget(opts, "PCREMaxFileSize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_PCRE_MAX_FILESIZE, opt->numarg))) { logg("!cli_engine_set_num(PCREMaxFileSize) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 1; @@ -946,18 +936,18 @@ if (optget(opts, "ArchiveBlockEncrypted")->enabled) { if (options.parse & CL_SCAN_PARSE_ARCHIVE) { logg( - "^Using deprecated option \"ArchiveBlockEncrypted\" to alert on " - "encrypted archives _and_ documents. Please update your " - "configuration to use replacement options \"AlertEncrypted\", or " - "\"AlertEncryptedArchive\" and/or \"AlertEncryptedDoc\".\n"); + "^Using deprecated option \"ArchiveBlockEncrypted\" to alert on " + "encrypted archives _and_ documents. Please update your " + "configuration to use replacement options \"AlertEncrypted\", or " + "\"AlertEncryptedArchive\" and/or \"AlertEncryptedDoc\".\n"); options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED_ARCHIVE; options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED_DOC; } else { logg( - "^Using deprecated option \"ArchiveBlockEncrypted\" to alert on " - "encrypted documents. Please update your configuration to use " - "replacement options \"AlertEncrypted\", or " - "\"AlertEncryptedArchive\" and/or \"AlertEncryptedDoc\".\n"); + "^Using deprecated option \"ArchiveBlockEncrypted\" to alert on " + "encrypted documents. Please update your configuration to use " + "replacement options \"AlertEncrypted\", or " + "\"AlertEncryptedArchive\" and/or \"AlertEncryptedDoc\".\n"); options.heuristic |= CL_SCAN_HEURISTIC_ENCRYPTED_DOC; } } @@ -1008,54 +998,54 @@ "replacement option \"HeuristicAlerts\".\n"); } else if (!optget(opts, "HeuristicAlerts")->enabled) { logg("Heuristic alerts disabled.\n"); - } else { - logg("Heuristic alerts enabled.\n"); - options.general |= CL_SCAN_GENERAL_HEURISTICS; + } else { + logg("Heuristic alerts enabled.\n"); + options.general |= CL_SCAN_GENERAL_HEURISTICS; } - if(optget(opts, "ScanPE")->enabled) { - logg("Portable Executable support enabled.\n"); - options.parse |= CL_SCAN_PARSE_PE; + if (optget(opts, "ScanPE")->enabled) { + logg("Portable Executable support enabled.\n"); + options.parse |= CL_SCAN_PARSE_PE; } else { - logg("Portable Executable support disabled.\n"); + logg("Portable Executable support disabled.\n"); } - if(optget(opts, "ScanELF")->enabled) { - logg("ELF support enabled.\n"); - options.parse |= CL_SCAN_PARSE_ELF; + if (optget(opts, "ScanELF")->enabled) { + logg("ELF support enabled.\n"); + options.parse |= CL_SCAN_PARSE_ELF; } else { - logg("ELF support disabled.\n"); + logg("ELF support disabled.\n"); } - /* TODO: Remove deprecated option in a future feature release */ + /* TODO: Remove deprecated option in a future feature release */ if (optget(opts, "ScanPE")->enabled || optget(opts, "ScanELF")->enabled) { if ((optget(opts, "DetectBrokenExecutables")->enabled) || - (optget(opts, "AlertBrokenExecutables")->enabled)) { + (optget(opts, "AlertBrokenExecutables")->enabled)) { logg("Alerting on broken executables enabled.\n"); options.heuristic |= CL_SCAN_HEURISTIC_BROKEN; } } - if(optget(opts, "ScanMail")->enabled) { - logg("Mail files support enabled.\n"); - options.parse |= CL_SCAN_PARSE_MAIL; - - if(optget(opts, "ScanPartialMessages")->enabled) { - logg("Mail: RFC1341 handling enabled.\n"); - options.mail |= CL_SCAN_MAIL_PARTIAL_MESSAGE; - } + if (optget(opts, "ScanMail")->enabled) { + logg("Mail files support enabled.\n"); + options.parse |= CL_SCAN_PARSE_MAIL; + + if (optget(opts, "ScanPartialMessages")->enabled) { + logg("Mail: RFC1341 handling enabled.\n"); + options.mail |= CL_SCAN_MAIL_PARTIAL_MESSAGE; + } } else { - logg("Mail files support disabled.\n"); + logg("Mail files support disabled.\n"); } if (optget(opts, "ScanOLE2")->enabled) { logg("OLE2 support enabled.\n"); options.parse |= CL_SCAN_PARSE_OLE2; - /* TODO: Remove deprecated option in a future feature release */ + /* TODO: Remove deprecated option in a future feature release */ if ((optget(opts, "OLE2BlockMacros")->enabled) || - (optget(opts, "AlertOLE2Macros")->enabled)) { + (optget(opts, "AlertOLE2Macros")->enabled)) { logg("OLE2: Alerting on all VBA macros.\n"); options.heuristic |= CL_SCAN_HEURISTIC_MACROS; } @@ -1063,49 +1053,59 @@ logg("OLE2 support disabled.\n"); } - if(optget(opts, "ScanPDF")->enabled) { - logg("PDF support enabled.\n"); - options.parse |= CL_SCAN_PARSE_PDF; + if (optget(opts, "ScanPDF")->enabled) { + logg("PDF support enabled.\n"); + options.parse |= CL_SCAN_PARSE_PDF; } else { - logg("PDF support disabled.\n"); + logg("PDF support disabled.\n"); } - if(optget(opts, "ScanSWF")->enabled) { - logg("SWF support enabled.\n"); - options.parse |= CL_SCAN_PARSE_SWF; + if (optget(opts, "ScanSWF")->enabled) { + logg("SWF support enabled.\n"); + options.parse |= CL_SCAN_PARSE_SWF; } else { - logg("SWF support disabled.\n"); + logg("SWF support disabled.\n"); } - if(optget(opts, "ScanHTML")->enabled) { - logg("HTML support enabled.\n"); - options.parse |= CL_SCAN_PARSE_HTML; + if (optget(opts, "ScanHTML")->enabled) { + logg("HTML support enabled.\n"); + options.parse |= CL_SCAN_PARSE_HTML; } else { - logg("HTML support disabled.\n"); + logg("HTML support disabled.\n"); + } + + #ifdef PRELUDE + if (optget(opts, "PreludeEnable")->enabled){ + if ((opt = optget(opts, "PreludeAnalyzerName"))->enabled){ + prelude_initialize_client(opt->strarg); + } else { + prelude_initialize_client("ClamAV"); + } } + #endif - if(optget(opts, "ScanXMLDOCS")->enabled) { - logg("XMLDOCS support enabled.\n"); - options.parse |= CL_SCAN_PARSE_XMLDOCS; + if (optget(opts, "ScanXMLDOCS")->enabled) { + logg("XMLDOCS support enabled.\n"); + options.parse |= CL_SCAN_PARSE_XMLDOCS; } else { - logg("XMLDOCS support disabled.\n"); + logg("XMLDOCS support disabled.\n"); } - if(optget(opts, "ScanHWP3")->enabled) { - logg("HWP3 support enabled.\n"); - options.parse |= CL_SCAN_PARSE_HWP3; + if (optget(opts, "ScanHWP3")->enabled) { + logg("HWP3 support enabled.\n"); + options.parse |= CL_SCAN_PARSE_HWP3; } else { - logg("HWP3 support disabled.\n"); + logg("HWP3 support disabled.\n"); } if (optget(opts, "PhishingScanURLs")->enabled) { - /* TODO: Remove deprecated option in a future feature release */ + /* TODO: Remove deprecated option in a future feature release */ if ((optget(opts, "PhishingAlwaysBlockCloak")->enabled) || (optget(opts, "AlertPhishingCloak")->enabled)) { options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_CLOAK; logg("Phishing: Always checking for cloaked urls\n"); } - /* TODO: Remove deprecated option in a future feature release */ + /* TODO: Remove deprecated option in a future feature release */ if ((optget(opts, "PhishingAlwaysBlockSSLMismatch")->enabled) || (optget(opts, "AlertPhishingSSLMismatch")->enabled)) { options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH; @@ -1113,212 +1113,170 @@ } } - /* TODO: Remove deprecated option in a future feature release */ - if ((optget(opts,"PartitionIntersection")->enabled) || - (optget(opts,"AlertPartitionIntersection")->enabled)) { + /* TODO: Remove deprecated option in a future feature release */ + if ((optget(opts, "PartitionIntersection")->enabled) || + (optget(opts, "AlertPartitionIntersection")->enabled)) { options.heuristic |= CL_SCAN_HEURISTIC_PARTITION_INTXN; logg("Raw DMG: Alert on partitions intersections\n"); } - if(optget(opts,"HeuristicScanPrecedence")->enabled) { - options.general |= CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE; - logg("Heuristic: precedence enabled\n"); + if (optget(opts, "HeuristicScanPrecedence")->enabled) { + options.general |= CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE; + logg("Heuristic: precedence enabled\n"); } - if(optget(opts, "StructuredDataDetection")->enabled) { + if (optget(opts, "StructuredDataDetection")->enabled) { options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED; - if((opt = optget(opts, "StructuredMinCreditCardCount"))->enabled) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) { - logg("!cl_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret)); - cl_engine_free(engine); - return 1; - } - } - val = cl_engine_get_num(engine, CL_ENGINE_MIN_CC_COUNT, NULL); - logg("Structured: Minimum Credit Card Number Count set to %u\n", (unsigned int) val); - - if((opt = optget(opts, "StructuredMinSSNCount"))->enabled) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) { - logg("!cl_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret)); - cl_engine_free(engine); - return 1; - } - } - val = cl_engine_get_num(engine, CL_ENGINE_MIN_SSN_COUNT, NULL); - logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int) val); + if ((opt = optget(opts, "StructuredMinCreditCardCount"))->enabled) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) { + logg("!cl_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret)); + cl_engine_free(engine); + return 1; + } + } + val = cl_engine_get_num(engine, CL_ENGINE_MIN_CC_COUNT, NULL); + logg("Structured: Minimum Credit Card Number Count set to %u\n", (unsigned int)val); + + if ((opt = optget(opts, "StructuredMinSSNCount"))->enabled) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) { + logg("!cl_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret)); + cl_engine_free(engine); + return 1; + } + } + val = cl_engine_get_num(engine, CL_ENGINE_MIN_SSN_COUNT, NULL); + logg("Structured: Minimum Social Security Number Count set to %u\n", (unsigned int)val); - if(optget(opts, "StructuredSSNFormatNormal")->enabled) + if (optget(opts, "StructuredSSNFormatNormal")->enabled) options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL; - if(optget(opts, "StructuredSSNFormatStripped")->enabled) - options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED; + if (optget(opts, "StructuredSSNFormatStripped")->enabled) + options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED; } #ifdef HAVE__INTERNAL__SHA_COLLECT - if(optget(opts, "DevCollectHashes")->enabled) - options.dev |= CL_SCAN_DEV_COLLECT_SHA; + if (optget(opts, "DevCollectHashes")->enabled) + options.dev |= CL_SCAN_DEV_COLLECT_SHA; #endif selfchk = optget(opts, "SelfCheck")->numarg; - if(!selfchk) { - logg("Self checking disabled.\n"); + if (!selfchk) { + logg("Self checking disabled.\n"); } else { - logg("Self checking every %u seconds.\n", selfchk); + logg("Self checking every %u seconds.\n", selfchk); } /* save the PID */ mainpid = getpid(); - if((opt = optget(opts, "PidFile"))->enabled) { - FILE *fd; - old_umask = umask(0002); - if((fd = fopen(opt->strarg, "w")) == NULL) { - logg("!Can't save PID in file %s\n", opt->strarg); - } else { - if (fprintf(fd, "%u\n", (unsigned int) mainpid)<0) { - logg("!Can't save PID in file %s\n", opt->strarg); - } - fclose(fd); - } - umask(old_umask); - } - - logg("*Listening daemon: PID: %u\n", (unsigned int) mainpid); - max_threads = optget(opts, "MaxThreads")->numarg; - max_queue = optget(opts, "MaxQueue")->numarg; + if ((opt = optget(opts, "PidFile"))->enabled) { + FILE *fd; + old_umask = umask(0002); + if ((fd = fopen(opt->strarg, "w")) == NULL) { + logg("!Can't save PID in file %s\n", opt->strarg); + } else { + if (fprintf(fd, "%u\n", (unsigned int)mainpid) < 0) { + logg("!Can't save PID in file %s\n", opt->strarg); + } + fclose(fd); + } + umask(old_umask); + } + + logg("*Listening daemon: PID: %u\n", (unsigned int)mainpid); + max_threads = optget(opts, "MaxThreads")->numarg; + max_queue = optget(opts, "MaxQueue")->numarg; acceptdata.commandtimeout = optget(opts, "CommandReadTimeout")->numarg; - readtimeout = optget(opts, "ReadTimeout")->numarg; + readtimeout = optget(opts, "ReadTimeout")->numarg; #if !defined(_WIN32) && defined(RLIMIT_NOFILE) if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { - /* don't warn if default value is too high, silently fix it */ - unsigned maxrec; - int max_max_queue; - unsigned warn = optget(opts, "MaxQueue")->active; - const unsigned clamdfiles = 6; + /* don't warn if default value is too high, silently fix it */ + unsigned maxrec; + int max_max_queue; + unsigned warn = optget(opts, "MaxQueue")->active; + const unsigned clamdfiles = 6; #ifdef C_SOLARIS - int solaris_has_extended_stdio = 0; + int solaris_has_extended_stdio = 0; #endif - /* Condition to not run out of file descriptors: - * MaxThreads * MaxRecursion + (MaxQueue - MaxThreads) + CLAMDFILES < RLIMIT_NOFILE - * CLAMDFILES is 6: 3 standard FD + logfile + 2 FD for reloading the DB - * */ + /* Condition to not run out of file descriptors: + * MaxThreads * MaxRecursion + (MaxQueue - MaxThreads) + CLAMDFILES < RLIMIT_NOFILE + * CLAMDFILES is 6: 3 standard FD + logfile + 2 FD for reloading the DB + * */ #ifdef C_SOLARIS - /* - ** If compiling 64bit, then set the solaris_has_extended_stdio - ** flag - */ + /* + ** If compiling 64bit, then set the solaris_has_extended_stdio + ** flag + */ #if defined(_LP64) - solaris_has_extended_stdio++; + solaris_has_extended_stdio++; #endif #ifdef HAVE_ENABLE_EXTENDED_FILE_STDIO - if (enable_extended_FILE_stdio(-1, -1) == -1) { - logg("^Unable to set extended FILE stdio, clamd will be limited to max 256 open files\n"); - rlim.rlim_cur = rlim.rlim_cur > 255 ? 255 : rlim.rlim_cur; - } - else - { - solaris_has_extended_stdio++; - } + if (enable_extended_FILE_stdio(-1, -1) == -1) { + logg("^Unable to set extended FILE stdio, clamd will be limited to max 256 open files\n"); + rlim.rlim_cur = rlim.rlim_cur > 255 ? 255 : rlim.rlim_cur; + } else { + solaris_has_extended_stdio++; + } #elif !defined(_LP64) - if (solaris_has_extended_stdio && rlim.rlim_cur > 255) { - rlim.rlim_cur = 255; - logg("^Solaris only supports 256 open files for 32-bit processes, you need at least Solaris 10u4, or compile as 64-bit to support more!\n"); - } -#endif - - /* - ** If compiling in 64bit or the file stdio has been extended, - ** then increase the soft limit for the number of open files - ** as the default is usually 256 - */ - - if (solaris_has_extended_stdio) - { - rlim_t saved_soft_limit = rlim.rlim_cur; - - rlim.rlim_cur = rlim.rlim_max; - if (setrlimit (RLIMIT_NOFILE, &rlim) < 0) - { - logg("!setrlimit() for RLIMIT_NOFILE to %lu failed: %s\n", - (unsigned long) rlim.rlim_cur, strerror (errno)); - rlim.rlim_cur = saved_soft_limit; - } - } /* If 64bit or has extended stdio */ - -#endif - opt = optget(opts,"MaxRecursion"); - maxrec = opt->numarg; - max_max_queue = rlim.rlim_cur - maxrec * max_threads - clamdfiles + max_threads; - if (max_queue < max_threads) { - max_queue = max_threads; - if (warn) - logg("^MaxQueue value too low, increasing to: %d\n", max_queue); - } - if (max_max_queue < max_threads) { - logg("^MaxThreads * MaxRecursion is too high: %d, open file descriptor limit is: %lu\n", - maxrec*max_threads, (unsigned long)rlim.rlim_cur); - max_max_queue = max_threads; - } - if (max_queue > max_max_queue) { - max_queue = max_max_queue; - if (warn) - logg("^MaxQueue value too high, lowering to: %d\n", max_queue); - } else if (max_queue < 2*max_threads && max_queue < max_max_queue) { - max_queue = 2*max_threads; - if (max_queue > max_max_queue) - max_queue = max_max_queue; - /* always warn here */ - logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue); - } - } + if (solaris_has_extended_stdio && rlim.rlim_cur > 255) { + rlim.rlim_cur = 255; + logg("^Solaris only supports 256 open files for 32-bit processes, you need at least Solaris 10u4, or compile as 64-bit to support more!\n"); + } #endif - logg("*MaxQueue set to: %d\n", max_queue); - acceptdata.max_queue = max_queue; - if(optget(opts, "ScanOnAccess")->enabled) + /* + ** If compiling in 64bit or the file stdio has been extended, + ** then increase the soft limit for the number of open files + ** as the default is usually 256 + */ + + if (solaris_has_extended_stdio) { + rlim_t saved_soft_limit = rlim.rlim_cur; + + rlim.rlim_cur = rlim.rlim_max; + if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { + logg("!setrlimit() for RLIMIT_NOFILE to %lu failed: %s\n", + (unsigned long)rlim.rlim_cur, strerror(errno)); + rlim.rlim_cur = saved_soft_limit; + } + } /* If 64bit or has extended stdio */ -#if defined(FANOTIFY) || defined(CLAMAUTH) - { - int thread_started = 1; - do { - if(pthread_attr_init(&fan_attr)) break; - pthread_attr_setdetachstate(&fan_attr, PTHREAD_CREATE_JOINABLE); - - /* Allocate memory for arguments. Thread is responsible for freeing it. */ - if (!(tharg = (struct thrarg *) calloc(sizeof(struct thrarg), 1))) break; - if (!(tharg->options = (struct cl_scan_options *) calloc(sizeof(struct cl_scan_options), 1))) break; - - (void) memcpy(tharg->options, &options, sizeof(struct cl_scan_options)); - tharg->opts = opts; - tharg->engine = engine; - - thread_started = pthread_create(&fan_pid, &fan_attr, onas_fan_th, tharg); - } while(0); - - if (0 != thread_started) { - /* Failed to create thread. Free anything we may have allocated. */ - logg("!Unable to start on-access scan.\n"); - if (NULL != tharg) { - if (NULL != tharg->options) { - free(tharg->options); - tharg->options = NULL; - } - free(tharg); - tharg = NULL; - } - } +#endif + opt = optget(opts, "MaxRecursion"); + maxrec = opt->numarg; + max_max_queue = rlim.rlim_cur - maxrec * max_threads - clamdfiles + max_threads; + if (max_queue < max_threads) { + max_queue = max_threads; + if (warn) + logg("^MaxQueue value too low, increasing to: %d\n", max_queue); + } + if (max_max_queue < max_threads) { + logg("^MaxThreads * MaxRecursion is too high: %d, open file descriptor limit is: %lu\n", + maxrec * max_threads, (unsigned long)rlim.rlim_cur); + max_max_queue = max_threads; + } + if (max_queue > max_max_queue) { + max_queue = max_max_queue; + if (warn) + logg("^MaxQueue value too high, lowering to: %d\n", max_queue); + } else if (max_queue < 2 * max_threads && max_queue < max_max_queue) { + max_queue = 2 * max_threads; + if (max_queue > max_max_queue) + max_queue = max_max_queue; + /* always warn here */ + logg("^MaxQueue is lower than twice MaxThreads, increasing to: %d\n", max_queue); + } } -#else - logg("!On-access scan is not available\n"); #endif + logg("*MaxQueue set to: %d\n", max_queue); + acceptdata.max_queue = max_queue; - -#ifndef _WIN32 +#ifndef _WIN32 /* set up signal handling */ sigfillset(&sigset); sigdelset(&sigset, SIGINT); @@ -1356,262 +1314,251 @@ idletimeout = optget(opts, "IdleTimeout")->numarg; - for (i=0;i < nsockets;i++) - if (fds_add(&acceptdata.fds, socketds[i], 1, 0) == -1) { - logg("!fds_add failed\n"); - cl_engine_free(engine); - return 1; - } + for (i = 0; i < nsockets; i++) + if (fds_add(&acceptdata.fds, socketds[i], 1, 0) == -1) { + logg("!fds_add failed\n"); + cl_engine_free(engine); + return 1; + } #ifdef _WIN32 - event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL); - event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL); + event_wake_accept = CreateEvent(NULL, TRUE, FALSE, NULL); + event_wake_recv = CreateEvent(NULL, TRUE, FALSE, NULL); #else if (pipe(acceptdata.syncpipe_wake_recv) == -1 || - (pipe(acceptdata.syncpipe_wake_accept) == -1)) { + (pipe(acceptdata.syncpipe_wake_accept) == -1)) { - logg("!pipe failed\n"); - exit(-1); + logg("!pipe failed\n"); + exit(-1); } syncpipe_wake_recv_w = acceptdata.syncpipe_wake_recv[1]; if (fds_add(fds, acceptdata.syncpipe_wake_recv[0], 1, 0) == -1 || - fds_add(&acceptdata.fds, acceptdata.syncpipe_wake_accept[0], 1, 0)) { - logg("!failed to add pipe fd\n"); - exit(-1); + fds_add(&acceptdata.fds, acceptdata.syncpipe_wake_accept[0], 1, 0)) { + logg("!failed to add pipe fd\n"); + exit(-1); } #endif if ((thr_pool = thrmgr_new(max_threads, idletimeout, max_queue, scanner_thread)) == NULL) { - logg("!thrmgr_new failed\n"); - exit(-1); + logg("!thrmgr_new failed\n"); + exit(-1); } if (pthread_create(&accept_th, NULL, acceptloop_th, &acceptdata)) { - logg("!pthread_create failed\n"); - exit(-1); + logg("!pthread_create failed\n"); + exit(-1); } time(&start_time); - for(;;) { - int new_sd; + for (;;) { + int new_sd; - /* Block waiting for connection on any of the sockets */ - pthread_mutex_lock(fds->buf_mutex); - fds_cleanup(fds); - /* signal that we can accept more connections */ - if (fds->nfds <= (unsigned)max_queue) - pthread_cond_signal(&acceptdata.cond_nfds); - new_sd = fds_poll_recv(fds, selfchk ? (int)selfchk : -1, 1, event_wake_recv); + /* Block waiting for connection on any of the sockets */ + pthread_mutex_lock(fds->buf_mutex); + fds_cleanup(fds); + /* signal that we can accept more connections */ + if (fds->nfds <= (unsigned)max_queue) + pthread_cond_signal(&acceptdata.cond_nfds); + new_sd = fds_poll_recv(fds, selfchk ? (int)selfchk : -1, 1, event_wake_recv); #ifdef _WIN32 - ResetEvent(event_wake_recv); + ResetEvent(event_wake_recv); #else - if (!fds->nfds) { - /* at least the dummy/sync pipe should have remained */ - logg("!All recv() descriptors gone: fatal\n"); - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - pthread_mutex_unlock(fds->buf_mutex); - break; - } -#endif - if (new_sd == -1 && errno != EINTR) { - logg("!Failed to poll sockets, fatal\n"); - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - } - - - if(fds->nfds) i = (rr_last + 1) % fds->nfds; - for (j = 0; j < fds->nfds && new_sd >= 0; j++, i = (i+1) % fds->nfds) { - size_t pos = 0; - int error = 0; - struct fd_buf *buf = &fds->buf[i]; - if (!buf->got_newdata) - continue; + if (!fds->nfds) { + /* at least the dummy/sync pipe should have remained */ + logg("!All recv() descriptors gone: fatal\n"); + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + pthread_mutex_unlock(fds->buf_mutex); + break; + } +#endif + if (new_sd == -1 && errno != EINTR) { + logg("!Failed to poll sockets, fatal\n"); + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + } + + if (fds->nfds) i = (rr_last + 1) % fds->nfds; + for (j = 0; j < fds->nfds && new_sd >= 0; j++, i = (i + 1) % fds->nfds) { + size_t pos = 0; + int error = 0; + struct fd_buf *buf = &fds->buf[i]; + if (!buf->got_newdata) + continue; #ifndef _WIN32 - if (buf->fd == acceptdata.syncpipe_wake_recv[0]) { - /* dummy sync pipe, just to wake us */ - if (read(buf->fd, buff, sizeof(buff)) < 0) { - logg("^Syncpipe read failed\n"); - } - continue; - } -#endif - if (buf->got_newdata == -1) { - if (buf->mode == MODE_WAITREPLY) { - logg("$mode WAIT_REPLY -> closed\n"); - buf->fd = -1; - thrmgr_group_terminate(buf->group); - thrmgr_group_finished(buf->group, EXIT_ERROR); - continue; - } else { - logg("$client read error or EOF on read\n"); - error = 1; - } - } - - if (buf->fd != -1 && buf->got_newdata == -2) { - logg("$Client read timed out\n"); - mdprintf(buf->fd, "COMMAND READ TIMED OUT\n"); - error = 1; - } - - rr_last = i; - if (buf->mode == MODE_WAITANCILL) { - buf->mode = MODE_COMMAND; - logg("$mode -> MODE_COMMAND\n"); - } - while (!error && buf->fd != -1 && buf->buffer && pos < buf->off && - buf->mode != MODE_WAITANCILL) { - client_conn_t conn; - const char *cmd = NULL; - int rc; - /* New data available to read on socket. */ - - memset(&conn, 0, sizeof(conn)); - conn.scanfd = buf->recvfd; - buf->recvfd = -1; - conn.sd = buf->fd; - conn.options = &options; - conn.opts = opts; - conn.thrpool = thr_pool; - conn.engine = engine; - conn.group = buf->group; - conn.id = buf->id; - conn.quota = buf->quota; - conn.filename = buf->dumpname; - conn.mode = buf->mode; - conn.term = buf->term; - - /* Parse & dispatch command */ - cmd = parse_dispatch_cmd(&conn, buf, &pos, &error, opts, readtimeout); - - if (conn.mode == MODE_COMMAND && !cmd) - break; - if (!error) { - if (buf->mode == MODE_WAITREPLY && buf->off) { - /* Client is not supposed to send anything more */ - logg("^Client sent garbage after last command: %lu bytes\n", (unsigned long)buf->off); - buf->buffer[buf->off] = '\0'; - logg("$Garbage: %s\n", buf->buffer); - error = 1; - } else if (buf->mode == MODE_STREAM) { - rc = handle_stream(&conn, buf, opts, &error, &pos, readtimeout); - if (rc == -1) - break; - else - continue; - } - } - if (error && error != CL_ETIMEOUT) { - conn_reply_error(&conn, "Error processing command."); - } - } - if (error) { - if (buf->dumpfd != -1) { - close(buf->dumpfd); - if (buf->dumpname) { - cli_unlink(buf->dumpname); - free(buf->dumpname); - } - buf->dumpfd = -1; - } - thrmgr_group_terminate(buf->group); - if (thrmgr_group_finished(buf->group, EXIT_ERROR)) { - if (buf->fd < 0) { - logg("$Skipping shutdown of bad socket after error (FD %d)\n", buf->fd); - } - else { - logg("$Shutting down socket after error (FD %d)\n", buf->fd); - shutdown(buf->fd, 2); - closesocket(buf->fd); - } - } else - logg("$Socket not shut down due to active tasks\n"); - buf->fd = -1; - } - } - pthread_mutex_unlock(fds->buf_mutex); - - /* handle progexit */ - pthread_mutex_lock(&exit_mutex); - if (progexit) { - pthread_mutex_unlock(&exit_mutex); - pthread_mutex_lock(fds->buf_mutex); - if (sd_listen_fds(0) == 0) - { - /* only close the sockets, when not using systemd socket activation */ - for (i=0;i < fds->nfds; i++) - { - if (fds->buf[i].fd == -1) + if (buf->fd == acceptdata.syncpipe_wake_recv[0]) { + /* dummy sync pipe, just to wake us */ + if (read(buf->fd, buff, sizeof(buff)) < 0) { + logg("^Syncpipe read failed\n"); + } + continue; + } +#endif + if (buf->got_newdata == -1) { + if (buf->mode == MODE_WAITREPLY) { + logg("$mode WAIT_REPLY -> closed\n"); + buf->fd = -1; + thrmgr_group_terminate(buf->group); + thrmgr_group_finished(buf->group, EXIT_ERROR); continue; - thrmgr_group_terminate(fds->buf[i].group); - if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR)) - { - logg("$Shutdown closed fd %d\n", fds->buf[i].fd); - shutdown(fds->buf[i].fd, 2); - closesocket(fds->buf[i].fd); - fds->buf[i].fd = -1; + } else { + logg("$client read error or EOF on read\n"); + error = 1; + } + } + + if (buf->fd != -1 && buf->got_newdata == -2) { + logg("$Client read timed out\n"); + mdprintf(buf->fd, "COMMAND READ TIMED OUT\n"); + error = 1; + } + + rr_last = i; + if (buf->mode == MODE_WAITANCILL) { + buf->mode = MODE_COMMAND; + logg("$mode -> MODE_COMMAND\n"); + } + while (!error && buf->fd != -1 && buf->buffer && pos < buf->off && + buf->mode != MODE_WAITANCILL) { + client_conn_t conn; + const char *cmd = NULL; + int rc; + /* New data available to read on socket. */ + + memset(&conn, 0, sizeof(conn)); + conn.scanfd = buf->recvfd; + buf->recvfd = -1; + conn.sd = buf->fd; + conn.options = &options; + conn.opts = opts; + conn.thrpool = thr_pool; + conn.engine = engine; + conn.group = buf->group; + conn.id = buf->id; + conn.quota = buf->quota; + conn.filename = buf->dumpname; + conn.mode = buf->mode; + conn.term = buf->term; + + /* Parse & dispatch command */ + cmd = parse_dispatch_cmd(&conn, buf, &pos, &error, opts, readtimeout); + + if (conn.mode == MODE_COMMAND && !cmd) + break; + if (!error) { + if (buf->mode == MODE_WAITREPLY && buf->off) { + /* Client is not supposed to send anything more */ + logg("^Client sent garbage after last command: %lu bytes\n", (unsigned long)buf->off); + buf->buffer[buf->off] = '\0'; + logg("$Garbage: %s\n", buf->buffer); + error = 1; + } else if (buf->mode == MODE_STREAM) { + rc = handle_stream(&conn, buf, opts, &error, &pos, readtimeout); + if (rc == -1) + break; + else + continue; + } + } + if (error && error != CL_ETIMEOUT) { + conn_reply_error(&conn, "Error processing command."); + } + } + if (error) { + if (buf->dumpfd != -1) { + close(buf->dumpfd); + if (buf->dumpname) { + cli_unlink(buf->dumpname); + free(buf->dumpname); + } + buf->dumpfd = -1; + } + thrmgr_group_terminate(buf->group); + if (thrmgr_group_finished(buf->group, EXIT_ERROR)) { + if (buf->fd < 0) { + logg("$Skipping shutdown of bad socket after error (FD %d)\n", buf->fd); + } else { + logg("$Shutting down socket after error (FD %d)\n", buf->fd); + shutdown(buf->fd, 2); + closesocket(buf->fd); + } + } else + logg("$Socket not shut down due to active tasks\n"); + buf->fd = -1; + } + } + pthread_mutex_unlock(fds->buf_mutex); + + /* handle progexit */ + pthread_mutex_lock(&exit_mutex); + if (progexit) { + pthread_mutex_unlock(&exit_mutex); + pthread_mutex_lock(fds->buf_mutex); + if (sd_listen_fds(0) == 0) { + /* only close the sockets, when not using systemd socket activation */ + for (i = 0; i < fds->nfds; i++) { + if (fds->buf[i].fd == -1) + continue; + thrmgr_group_terminate(fds->buf[i].group); + if (thrmgr_group_finished(fds->buf[i].group, EXIT_ERROR)) { + logg("$Shutdown closed fd %d\n", fds->buf[i].fd); + shutdown(fds->buf[i].fd, 2); + closesocket(fds->buf[i].fd); + fds->buf[i].fd = -1; + } } } - } - pthread_mutex_unlock(fds->buf_mutex); - break; - } - pthread_mutex_unlock(&exit_mutex); - - /* SIGHUP */ - if (sighup) { - logg("SIGHUP caught: re-opening log file.\n"); - logg_close(); - sighup = 0; - if(!logg_file && (opt = optget(opts, "LogFile"))->enabled) - logg_file = opt->strarg; - } - - /* SelfCheck */ - if(selfchk) { - time(¤t_time); - if((current_time - start_time) >= (time_t)selfchk) { - if(reload_db(engine, dboptions, opts, TRUE, &ret)) { - pthread_mutex_lock(&reload_mutex); - reload = 1; - pthread_mutex_unlock(&reload_mutex); - } - time(&start_time); - } - } - - /* DB reload */ - pthread_mutex_lock(&reload_mutex); - if(reload) { - pthread_mutex_unlock(&reload_mutex); - - engine = reload_db(engine, dboptions, opts, FALSE, &ret); - if(ret) { - logg("Terminating because of a fatal error.\n"); - if(new_sd >= 0) - closesocket(new_sd); - break; - } - - pthread_mutex_lock(&reload_mutex); - reload = 0; - time(&reloaded_time); - pthread_mutex_unlock(&reload_mutex); - -#if defined(FANOTIFY) || defined(CLAMAUTH) - if(optget(opts, "ScanOnAccess")->enabled && tharg) { - tharg->engine = engine; - } -#endif - time(&start_time); - } else { - pthread_mutex_unlock(&reload_mutex); - } + pthread_mutex_unlock(fds->buf_mutex); + break; + } + pthread_mutex_unlock(&exit_mutex); + + /* SIGHUP */ + if (sighup) { + logg("SIGHUP caught: re-opening log file.\n"); + logg_close(); + sighup = 0; + if (!logg_file && (opt = optget(opts, "LogFile"))->enabled) + logg_file = opt->strarg; + } + + /* SelfCheck */ + if (selfchk) { + time(¤t_time); + if ((current_time - start_time) >= (time_t)selfchk) { + if (reload_db(engine, dboptions, opts, TRUE, &ret)) { + pthread_mutex_lock(&reload_mutex); + reload = 1; + pthread_mutex_unlock(&reload_mutex); + } + time(&start_time); + } + } + + /* DB reload */ + pthread_mutex_lock(&reload_mutex); + if (reload) { + pthread_mutex_unlock(&reload_mutex); + + engine = reload_db(engine, dboptions, opts, FALSE, &ret); + if (ret) { + logg("Terminating because of a fatal error.\n"); + if (new_sd >= 0) + closesocket(new_sd); + break; + } + + pthread_mutex_lock(&reload_mutex); + reload = 0; + time(&reloaded_time); + pthread_mutex_unlock(&reload_mutex); + time(&start_time); + } else { + pthread_mutex_unlock(&reload_mutex); + } } pthread_mutex_lock(&exit_mutex); @@ -1621,7 +1568,7 @@ SetEvent(event_wake_accept); #else if (write(acceptdata.syncpipe_wake_accept[1], "", 1) < 0) { - logg("^Write to syncpipe failed\n"); + logg("^Write to syncpipe failed\n"); } #endif /* Destroy the thread manager. @@ -1629,19 +1576,9 @@ */ logg("*Waiting for all threads to finish\n"); thrmgr_destroy(thr_pool); -#if defined(FANOTIFY) || defined(CLAMAUTH) - if(optget(opts, "ScanOnAccess")->enabled && tharg) { - logg("Stopping on-access scan\n"); - pthread_mutex_lock(&logg_mutex); - pthread_kill(fan_pid, SIGUSR1); - pthread_mutex_unlock(&logg_mutex); - pthread_join(fan_pid, NULL); - free(tharg); - } -#endif - if(engine) { - thrmgr_setactiveengine(NULL); - cl_engine_free(engine); + if (engine) { + thrmgr_setactiveengine(NULL); + cl_engine_free(engine); } pthread_join(accept_th, NULL); @@ -1655,21 +1592,20 @@ close(acceptdata.syncpipe_wake_accept[1]); close(acceptdata.syncpipe_wake_recv[1]); #endif - if(dbstat.entries) - cl_statfree(&dbstat); - if (sd_listen_fds(0) == 0) - { + if (dbstat.entries) + cl_statfree(&dbstat); + if (sd_listen_fds(0) == 0) { /* only close the sockets, when not using systemd socket activation */ logg("*Shutting down the main socket%s.\n", (nsockets > 1) ? "s" : ""); for (i = 0; i < nsockets; i++) shutdown(socketds[i], 2); } - if((opt = optget(opts, "PidFile"))->enabled) { - if(unlink(opt->strarg) == -1) - logg("!Can't unlink the pid file %s\n", opt->strarg); - else - logg("Pid file removed.\n"); + if ((opt = optget(opts, "PidFile"))->enabled) { + if (unlink(opt->strarg) == -1) + logg("!Can't unlink the pid file %s\n", opt->strarg); + else + logg("Pid file removed.\n"); } time(¤t_time); diff -Nru clamav-0.101.4+dfsg/clamd/server.h clamav-0.102.1+dfsg/clamd/server.h --- clamav-0.101.4+dfsg/clamd/server.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/server.h 2019-11-20 04:42:24.000000000 +0000 @@ -38,7 +38,7 @@ }; int recvloop_th(int *socketds, unsigned nsockets, struct cl_engine *engine, unsigned int dboptions, const struct optstruct *opts); -int statinidir_th(const char* dirname); +int statinidir_th(const char *dirname); void sighandler(int sig); void sighandler_th(int sig); void sigsegv(int sig); diff -Nru clamav-0.101.4+dfsg/clamd/session.c clamav-0.102.1+dfsg/clamd/session.c --- clamav-0.101.4+dfsg/clamd/session.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/session.c 2019-11-20 04:42:24.000000000 +0000 @@ -26,12 +26,12 @@ #include #include #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #include #include -#ifndef _WIN32 +#ifndef _WIN32 #include #ifdef HAVE_SYS_SELECT_H #include @@ -78,54 +78,53 @@ int support_old; int enabled; } commands[] = { - {CMD1, sizeof(CMD1)-1, COMMAND_SCAN, 1, 1, 0}, - {CMD3, sizeof(CMD3)-1, COMMAND_SHUTDOWN, 0, 1, 0}, - {CMD4, sizeof(CMD4)-1, COMMAND_RELOAD, 0, 1, 0}, - {CMD5, sizeof(CMD5)-1, COMMAND_PING, 0, 1, 0}, - {CMD6, sizeof(CMD6)-1, COMMAND_CONTSCAN, 1, 1, 0}, + {CMD1, sizeof(CMD1) - 1, COMMAND_SCAN, 1, 1, 0}, + {CMD3, sizeof(CMD3) - 1, COMMAND_SHUTDOWN, 0, 1, 0}, + {CMD4, sizeof(CMD4) - 1, COMMAND_RELOAD, 0, 1, 0}, + {CMD5, sizeof(CMD5) - 1, COMMAND_PING, 0, 1, 0}, + {CMD6, sizeof(CMD6) - 1, COMMAND_CONTSCAN, 1, 1, 0}, /* must be before VERSION, because they share common prefix! */ - {CMD18, sizeof(CMD18)-1, COMMAND_COMMANDS, 0, 0, 1}, - {CMD7, sizeof(CMD7)-1, COMMAND_VERSION, 0, 1, 1}, - {CMD8, sizeof(CMD8)-1, COMMAND_STREAM, 0, 1, 1}, - {CMD10, sizeof(CMD10)-1, COMMAND_END, 0, 0, 1}, - {CMD11, sizeof(CMD11)-1, COMMAND_SHUTDOWN, 0, 1, 1}, - {CMD13, sizeof(CMD13)-1, COMMAND_MULTISCAN, 1, 1, 1}, - {CMD14, sizeof(CMD14)-1, COMMAND_FILDES, 0, 1, FEATURE_FDPASSING}, - {CMD15, sizeof(CMD15)-1, COMMAND_STATS, 0, 0, 1}, - {CMD16, sizeof(CMD16)-1, COMMAND_IDSESSION, 0, 0, 1}, - {CMD17, sizeof(CMD17)-1, COMMAND_INSTREAM, 0, 0, 1}, - {CMD19, sizeof(CMD19)-1, COMMAND_DETSTATSCLEAR, 0, 1, 1}, - {CMD20, sizeof(CMD20)-1, COMMAND_DETSTATS, 0, 1, 1}, - {CMD21, sizeof(CMD21)-1, COMMAND_ALLMATCHSCAN, 1, 0, 1} -}; + {CMD18, sizeof(CMD18) - 1, COMMAND_COMMANDS, 0, 0, 1}, + {CMD7, sizeof(CMD7) - 1, COMMAND_VERSION, 0, 1, 1}, + {CMD8, sizeof(CMD8) - 1, COMMAND_STREAM, 0, 1, 1}, + {CMD10, sizeof(CMD10) - 1, COMMAND_END, 0, 0, 1}, + {CMD11, sizeof(CMD11) - 1, COMMAND_SHUTDOWN, 0, 1, 1}, + {CMD13, sizeof(CMD13) - 1, COMMAND_MULTISCAN, 1, 1, 1}, + {CMD14, sizeof(CMD14) - 1, COMMAND_FILDES, 0, 1, FEATURE_FDPASSING}, + {CMD15, sizeof(CMD15) - 1, COMMAND_STATS, 0, 0, 1}, + {CMD16, sizeof(CMD16) - 1, COMMAND_IDSESSION, 0, 0, 1}, + {CMD17, sizeof(CMD17) - 1, COMMAND_INSTREAM, 0, 0, 1}, + {CMD19, sizeof(CMD19) - 1, COMMAND_DETSTATSCLEAR, 0, 1, 1}, + {CMD20, sizeof(CMD20) - 1, COMMAND_DETSTATS, 0, 1, 1}, + {CMD21, sizeof(CMD21) - 1, COMMAND_ALLMATCHSCAN, 1, 0, 1}}; enum commands parse_command(const char *cmd, const char **argument, int oldstyle) { size_t i; *argument = NULL; - for (i=0; i < sizeof(commands)/sizeof(commands[0]); i++) { - const size_t len = commands[i].len; - if (!strncmp(cmd, commands[i].cmd, len)) { - const char *arg = cmd + len; - if (commands[i].need_arg) { - if (!*arg) {/* missing argument */ - logg("$Command %s missing argument!\n", commands[i].cmd); - return COMMAND_UNKNOWN; - } - *argument = arg+1; - } else { - if (*arg) {/* extra stuff after command */ - logg("$Command %s has trailing garbage!\n", commands[i].cmd); - return COMMAND_UNKNOWN; - } - *argument = NULL; - } - if (oldstyle && !commands[i].support_old) { - logg("$Command sent as old-style when not supported: %s\n", commands[i].cmd); - return COMMAND_UNKNOWN; - } - return commands[i].cmdtype; - } + for (i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { + const size_t len = commands[i].len; + if (!strncmp(cmd, commands[i].cmd, len)) { + const char *arg = cmd + len; + if (commands[i].need_arg) { + if (!*arg) { /* missing argument */ + logg("$Command %s missing argument!\n", commands[i].cmd); + return COMMAND_UNKNOWN; + } + *argument = arg + 1; + } else { + if (*arg) { /* extra stuff after command */ + logg("$Command %s has trailing garbage!\n", commands[i].cmd); + return COMMAND_UNKNOWN; + } + *argument = NULL; + } + if (oldstyle && !commands[i].support_old) { + logg("$Command sent as old-style when not supported: %s\n", commands[i].cmd); + return COMMAND_UNKNOWN; + } + return commands[i].cmdtype; + } } return COMMAND_UNKNOWN; } @@ -133,36 +132,36 @@ int conn_reply_single(const client_conn_t *conn, const char *path, const char *status) { if (conn->id) { - if (path) - return mdprintf(conn->sd, "%u: %s: %s%c", conn->id, path, status, conn->term); - return mdprintf(conn->sd, "%u: %s%c", conn->id, status, conn->term); + if (path) + return mdprintf(conn->sd, "%u: %s: %s%c", conn->id, path, status, conn->term); + return mdprintf(conn->sd, "%u: %s%c", conn->id, status, conn->term); } if (path) - return mdprintf(conn->sd, "%s: %s%c", path, status, conn->term); + return mdprintf(conn->sd, "%s: %s%c", path, status, conn->term); return mdprintf(conn->sd, "%s%c", status, conn->term); } int conn_reply(const client_conn_t *conn, const char *path, - const char *msg, const char *status) + const char *msg, const char *status) { if (conn->id) { - if (path) - return mdprintf(conn->sd, "%u: %s: %s %s%c", conn->id, path, msg, - status, conn->term); - return mdprintf(conn->sd, "%u: %s %s%c", conn->id, msg, status, - conn->term); + if (path) + return mdprintf(conn->sd, "%u: %s: %s %s%c", conn->id, path, msg, + status, conn->term); + return mdprintf(conn->sd, "%u: %s %s%c", conn->id, msg, status, + conn->term); } if (path) - return mdprintf(conn->sd, "%s: %s %s%c", path, msg, status, conn->term); + return mdprintf(conn->sd, "%s: %s %s%c", path, msg, status, conn->term); return mdprintf(conn->sd, "%s %s%c", msg, status, conn->term); } int conn_reply_virus(const client_conn_t *conn, const char *file, - const char *virname) + const char *virname) { if (conn->id) { - return mdprintf(conn->sd, "%u: %s: %s FOUND%c", conn->id, file, virname, - conn->term); + return mdprintf(conn->sd, "%u: %s: %s FOUND%c", conn->id, file, virname, + conn->term); } return mdprintf(conn->sd, "%s: %s FOUND%c", file, virname, conn->term); } @@ -174,10 +173,10 @@ #define BUFFSIZE 1024 int conn_reply_errno(const client_conn_t *conn, const char *path, - const char *msg) + const char *msg) { char err[BUFFSIZE + sizeof(". ERROR")]; - cli_strerror(errno, err, BUFFSIZE-1); + cli_strerror(errno, err, BUFFSIZE - 1); strcat(err, ". ERROR"); return conn_reply(conn, path, msg, err); } @@ -189,13 +188,13 @@ */ int command(client_conn_t *conn, int *virus) { - int desc = conn->sd; - struct cl_engine *engine = conn->engine; + int desc = conn->sd; + struct cl_engine *engine = conn->engine; struct cl_scan_options *options = conn->options; - const struct optstruct *opts = conn->opts; - enum scan_type type = TYPE_INIT; + const struct optstruct *opts = conn->opts; + enum scan_type type = TYPE_INIT; int maxdirrec; - int ret = 0; + int ret = 0; int flags = CLI_FTW_STD; struct scan_cb_data scandata; @@ -205,281 +204,280 @@ jobgroup_t *group = NULL; if (thrmgr_group_need_terminate(conn->group)) { - logg("$Client disconnected while command was active\n"); - if (conn->scanfd != -1) - close(conn->scanfd); - return 1; + logg("$Client disconnected while command was active\n"); + if (conn->scanfd != -1) + close(conn->scanfd); + return 1; } thrmgr_setactiveengine(engine); data.data = &scandata; memset(&scandata, 0, sizeof(scandata)); - scandata.id = conn->id; - scandata.group = conn->group; - scandata.odesc = desc; - scandata.conn = conn; - scandata.options = options; - scandata.engine = engine; - scandata.opts = opts; - scandata.thr_pool = conn->thrpool; + scandata.id = conn->id; + scandata.group = conn->group; + scandata.odesc = desc; + scandata.conn = conn; + scandata.options = options; + scandata.engine = engine; + scandata.opts = opts; + scandata.thr_pool = conn->thrpool; scandata.toplevel_path = conn->filename; switch (conn->cmdtype) { - case COMMAND_SCAN: - thrmgr_setactivetask(NULL, "SCAN"); - type = TYPE_SCAN; - break; - case COMMAND_CONTSCAN: - thrmgr_setactivetask(NULL, "CONTSCAN"); - type = TYPE_CONTSCAN; - break; - case COMMAND_MULTISCAN: { - int multiscan, max, alive; - - /* use MULTISCAN only for directories (bb #1869) */ - if (CLAMSTAT(conn->filename, &sb) == 0 && - !S_ISDIR(sb.st_mode)) { - thrmgr_setactivetask(NULL, "CONTSCAN"); - type = TYPE_CONTSCAN; - break; - } - - pthread_mutex_lock(&conn->thrpool->pool_mutex); - multiscan = conn->thrpool->thr_multiscan; - max = conn->thrpool->thr_max; - if (multiscan+1 < max) - conn->thrpool->thr_multiscan = multiscan+1; - else { - alive = conn->thrpool->thr_alive; - ret = -1; - } - pthread_mutex_unlock(&conn->thrpool->pool_mutex); - if (ret) { - /* multiscan has 1 control thread, so there needs to be at least + case COMMAND_SCAN: + thrmgr_setactivetask(NULL, "SCAN"); + type = TYPE_SCAN; + break; + case COMMAND_CONTSCAN: + thrmgr_setactivetask(NULL, "CONTSCAN"); + type = TYPE_CONTSCAN; + break; + case COMMAND_MULTISCAN: { + int multiscan, max, alive; + + /* use MULTISCAN only for directories (bb #1869) */ + if (CLAMSTAT(conn->filename, &sb) == 0 && + !S_ISDIR(sb.st_mode)) { + thrmgr_setactivetask(NULL, "CONTSCAN"); + type = TYPE_CONTSCAN; + break; + } + + pthread_mutex_lock(&conn->thrpool->pool_mutex); + multiscan = conn->thrpool->thr_multiscan; + max = conn->thrpool->thr_max; + if (multiscan + 1 < max) + conn->thrpool->thr_multiscan = multiscan + 1; + else { + alive = conn->thrpool->thr_alive; + ret = -1; + } + pthread_mutex_unlock(&conn->thrpool->pool_mutex); + if (ret) { + /* multiscan has 1 control thread, so there needs to be at least 1 threads that is a non-multiscan controlthread to scan and make progress. */ - logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n", - max, alive, multiscan); - conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.", "ERROR"); - return 1; - } - flags &= ~CLI_FTW_NEED_STAT; - thrmgr_setactivetask(NULL, "MULTISCAN"); - type = TYPE_MULTISCAN; - scandata.group = group = thrmgr_group_new(); - if (!group) { - if(optget(opts, "ExitOnOOM")->enabled) - return -1; - else - return 1; - } - break; - } - case COMMAND_MULTISCANFILE: - thrmgr_setactivetask(NULL, "MULTISCANFILE"); - scandata.group = NULL; - scandata.type = TYPE_SCAN; - scandata.thr_pool = NULL; - /* TODO: check ret value */ - ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data); /* callback freed it */ - conn->filename = NULL; - *virus = scandata.infected; - if (ret == CL_BREAK) { - thrmgr_group_terminate(conn->group); - return 1; - } - return scandata.errors > 0 ? scandata.errors : 0; - case COMMAND_FILDES: - thrmgr_setactivetask(NULL, "FILDES"); + logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n", + max, alive, multiscan); + conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.", "ERROR"); + return 1; + } + flags &= ~CLI_FTW_NEED_STAT; + thrmgr_setactivetask(NULL, "MULTISCAN"); + type = TYPE_MULTISCAN; + scandata.group = group = thrmgr_group_new(); + if (!group) { + if (optget(opts, "ExitOnOOM")->enabled) + return -1; + else + return 1; + } + break; + } + case COMMAND_MULTISCANFILE: + thrmgr_setactivetask(NULL, "MULTISCANFILE"); + scandata.group = NULL; + scandata.type = TYPE_SCAN; + scandata.thr_pool = NULL; + /* TODO: check ret value */ + ret = scan_callback(NULL, conn->filename, conn->filename, visit_file, &data); /* callback freed it */ + conn->filename = NULL; + *virus = scandata.infected; + if (ret == CL_BREAK) { + thrmgr_group_terminate(conn->group); + return 1; + } + return scandata.errors > 0 ? scandata.errors : 0; + case COMMAND_FILDES: + thrmgr_setactivetask(NULL, "FILDES"); #ifdef HAVE_FD_PASSING - if (conn->scanfd == -1) { - conn_reply_error(conn, "FILDES: didn't receive file descriptor."); - return 1; - } - else { - ret = scanfd(conn, NULL, engine, options, opts, desc, 0); - if (ret == CL_VIRUS) { - *virus = 1; - ret = 0; - } else if (ret == CL_EMEM) { - if(optget(opts, "ExitOnOOM")->enabled) - ret = -1; - else - ret = 1; - } else if (ret == CL_ETIMEOUT) { - thrmgr_group_terminate(conn->group); - ret = 1; - } else - ret = 0; - logg("$Closed fd %d\n", conn->scanfd); - close(conn->scanfd); - } - return ret; + if (conn->scanfd == -1) { + conn_reply_error(conn, "FILDES: didn't receive file descriptor."); + return 1; + } else { + ret = scanfd(conn, NULL, engine, options, opts, desc, 0); + if (ret == CL_VIRUS) { + *virus = 1; + ret = 0; + } else if (ret == CL_EMEM) { + if (optget(opts, "ExitOnOOM")->enabled) + ret = -1; + else + ret = 1; + } else if (ret == CL_ETIMEOUT) { + thrmgr_group_terminate(conn->group); + ret = 1; + } else + ret = 0; + logg("$Closed fd %d\n", conn->scanfd); + close(conn->scanfd); + } + return ret; #else - conn_reply_error(conn, "FILDES support not compiled in."); - close(conn->scanfd); - return 0; - #endif - case COMMAND_STATS: - thrmgr_setactivetask(NULL, "STATS"); - if (conn->group) - mdprintf(desc, "%u: ", conn->id); - thrmgr_printstats(desc, conn->term); - return 0; - case COMMAND_STREAM: - thrmgr_setactivetask(NULL, "STREAM"); - ret = scanstream(desc, NULL, engine, options, opts, conn->term); - if (ret == CL_VIRUS) - *virus = 1; - if (ret == CL_EMEM) { - if(optget(opts, "ExitOnOOM")->enabled) - return -1; - else - return 1; - } - return 0; - case COMMAND_INSTREAMSCAN: - thrmgr_setactivetask(NULL, "INSTREAM"); - ret = scanfd(conn, NULL, engine, options, opts, desc, 1); - if (ret == CL_VIRUS) { - *virus = 1; - ret = 0; - } else if (ret == CL_EMEM) { - if(optget(opts, "ExitOnOOM")->enabled) - ret = -1; - else - ret = 1; - } else if (ret == CL_ETIMEOUT) { - thrmgr_group_terminate(conn->group); - ret = 1; - } else - ret = 0; - if (ftruncate(conn->scanfd, 0) == -1) { - /* not serious, we're going to close it and unlink it anyway */ - logg("*ftruncate failed: %d\n", errno); - } - close(conn->scanfd); - conn->scanfd = -1; - cli_unlink(conn->filename); - return ret; - case COMMAND_ALLMATCHSCAN: - if (!optget(opts, "AllowAllMatchScan")->enabled) { - logg("$Rejecting ALLMATCHSCAN command.\n"); - conn_reply(conn, conn->filename, "ALLMATCHSCAN command disabled by clamd configuration.", "ERROR"); - return 1; - } - thrmgr_setactivetask(NULL, "ALLMATCHSCAN"); - scandata.options->general |= CL_SCAN_GENERAL_ALLMATCHES; - type = TYPE_SCAN; - break; - default: - logg("!Invalid command dispatched: %d\n", conn->cmdtype); - return 1; - } - - scandata.type = type; - maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg; - if (optget(opts, "FollowDirectorySymlinks")->enabled) - flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; - if (optget(opts, "FollowFileSymlinks")->enabled) - flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; - - if(!optget(opts, "CrossFilesystems")->enabled) - if(CLAMSTAT(conn->filename, &sb) == 0) - scandata.dev = sb.st_dev; - - ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk); - if (ret == CL_EMEM) { - if(optget(opts, "ExitOnOOM")->enabled) - return -1; - else - return 1; - } - if (scandata.group && type == TYPE_MULTISCAN) { - thrmgr_group_waitforall(group, &ok, &error, &total); - pthread_mutex_lock(&conn->thrpool->pool_mutex); - conn->thrpool->thr_multiscan--; - pthread_mutex_unlock(&conn->thrpool->pool_mutex); - } else { - error = scandata.errors; - total = scandata.total; - ok = total - error - scandata.infected; - } - - if (ok + error == total && (error != total)) { - if (conn_reply_single(conn, conn->filename, "OK") == -1) - ret = CL_ETIMEOUT; - } - *virus = total - (ok + error); - - if (ret == CL_ETIMEOUT) - thrmgr_group_terminate(conn->group); - return error; - } - - static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument) - { - int ret = 0; - int bulk; - client_conn_t *dup_conn = (client_conn_t *) malloc(sizeof(struct client_conn_tag)); - - if(!dup_conn) { - logg("!Can't allocate memory for client_conn\n"); - return -1; - } - memcpy(dup_conn, conn, sizeof(*conn)); - dup_conn->cmdtype = cmd; - if(cl_engine_addref(dup_conn->engine)) { - logg("!cl_engine_addref() failed\n"); - free(dup_conn); - return -1; - } - dup_conn->scanfd = -1; - bulk = 1; - switch (cmd) { - case COMMAND_FILDES: - if (conn->scanfd == -1) { - conn_reply_error(dup_conn, "No file descriptor received."); - ret = 1; - } - dup_conn->scanfd = conn->scanfd; - /* consume FD */ - conn->scanfd = -1; - break; - case COMMAND_SCAN: - case COMMAND_CONTSCAN: - case COMMAND_MULTISCAN: - case COMMAND_ALLMATCHSCAN: - dup_conn->filename = cli_strdup_to_utf8(argument); - if (!dup_conn->filename) { - logg("!Failed to allocate memory for filename\n"); - ret = -1; - } - break; - case COMMAND_INSTREAMSCAN: - dup_conn->scanfd = conn->scanfd; - conn->scanfd = -1; - break; - case COMMAND_STREAM: - case COMMAND_STATS: - /* not a scan command, don't queue to bulk */ - bulk = 0; - /* just dispatch the command */ - break; - default: - logg("!Invalid command dispatch: %d\n", cmd); - ret = -2; - break; + conn_reply_error(conn, "FILDES support not compiled in."); + close(conn->scanfd); + return 0; +#endif + case COMMAND_STATS: + thrmgr_setactivetask(NULL, "STATS"); + if (conn->group) + mdprintf(desc, "%u: ", conn->id); + thrmgr_printstats(desc, conn->term); + return 0; + case COMMAND_STREAM: + thrmgr_setactivetask(NULL, "STREAM"); + ret = scanstream(desc, NULL, engine, options, opts, conn->term); + if (ret == CL_VIRUS) + *virus = 1; + if (ret == CL_EMEM) { + if (optget(opts, "ExitOnOOM")->enabled) + return -1; + else + return 1; + } + return 0; + case COMMAND_INSTREAMSCAN: + thrmgr_setactivetask(NULL, "INSTREAM"); + ret = scanfd(conn, NULL, engine, options, opts, desc, 1); + if (ret == CL_VIRUS) { + *virus = 1; + ret = 0; + } else if (ret == CL_EMEM) { + if (optget(opts, "ExitOnOOM")->enabled) + ret = -1; + else + ret = 1; + } else if (ret == CL_ETIMEOUT) { + thrmgr_group_terminate(conn->group); + ret = 1; + } else + ret = 0; + if (ftruncate(conn->scanfd, 0) == -1) { + /* not serious, we're going to close it and unlink it anyway */ + logg("*ftruncate failed: %d\n", errno); + } + close(conn->scanfd); + conn->scanfd = -1; + cli_unlink(conn->filename); + return ret; + case COMMAND_ALLMATCHSCAN: + if (!optget(opts, "AllowAllMatchScan")->enabled) { + logg("$Rejecting ALLMATCHSCAN command.\n"); + conn_reply(conn, conn->filename, "ALLMATCHSCAN command disabled by clamd configuration.", "ERROR"); + return 1; + } + thrmgr_setactivetask(NULL, "ALLMATCHSCAN"); + scandata.options->general |= CL_SCAN_GENERAL_ALLMATCHES; + type = TYPE_SCAN; + break; + default: + logg("!Invalid command dispatched: %d\n", conn->cmdtype); + return 1; + } + + scandata.type = type; + maxdirrec = optget(opts, "MaxDirectoryRecursion")->numarg; + if (optget(opts, "FollowDirectorySymlinks")->enabled) + flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; + if (optget(opts, "FollowFileSymlinks")->enabled) + flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; + + if (!optget(opts, "CrossFilesystems")->enabled) + if (CLAMSTAT(conn->filename, &sb) == 0) + scandata.dev = sb.st_dev; + + ret = cli_ftw(conn->filename, flags, maxdirrec ? maxdirrec : INT_MAX, scan_callback, &data, scan_pathchk); + if (ret == CL_EMEM) { + if (optget(opts, "ExitOnOOM")->enabled) + return -1; + else + return 1; + } + if (scandata.group && type == TYPE_MULTISCAN) { + thrmgr_group_waitforall(group, &ok, &error, &total); + pthread_mutex_lock(&conn->thrpool->pool_mutex); + conn->thrpool->thr_multiscan--; + pthread_mutex_unlock(&conn->thrpool->pool_mutex); + } else { + error = scandata.errors; + total = scandata.total; + ok = total - error - scandata.infected; + } + + if (ok + error == total && (error != total)) { + if (conn_reply_single(conn, conn->filename, "OK") == -1) + ret = CL_ETIMEOUT; + } + *virus = total - (ok + error); + + if (ret == CL_ETIMEOUT) + thrmgr_group_terminate(conn->group); + return error; +} + +static int dispatch_command(client_conn_t *conn, enum commands cmd, const char *argument) +{ + int ret = 0; + int bulk; + client_conn_t *dup_conn = (client_conn_t *)malloc(sizeof(struct client_conn_tag)); + + if (!dup_conn) { + logg("!Can't allocate memory for client_conn\n"); + return -1; + } + memcpy(dup_conn, conn, sizeof(*conn)); + dup_conn->cmdtype = cmd; + if (cl_engine_addref(dup_conn->engine)) { + logg("!cl_engine_addref() failed\n"); + free(dup_conn); + return -1; + } + dup_conn->scanfd = -1; + bulk = 1; + switch (cmd) { + case COMMAND_FILDES: + if (conn->scanfd == -1) { + conn_reply_error(dup_conn, "No file descriptor received."); + ret = 1; + } + dup_conn->scanfd = conn->scanfd; + /* consume FD */ + conn->scanfd = -1; + break; + case COMMAND_SCAN: + case COMMAND_CONTSCAN: + case COMMAND_MULTISCAN: + case COMMAND_ALLMATCHSCAN: + dup_conn->filename = cli_strdup_to_utf8(argument); + if (!dup_conn->filename) { + logg("!Failed to allocate memory for filename\n"); + ret = -1; + } + break; + case COMMAND_INSTREAMSCAN: + dup_conn->scanfd = conn->scanfd; + conn->scanfd = -1; + break; + case COMMAND_STREAM: + case COMMAND_STATS: + /* not a scan command, don't queue to bulk */ + bulk = 0; + /* just dispatch the command */ + break; + default: + logg("!Invalid command dispatch: %d\n", cmd); + ret = -2; + break; } if (!dup_conn->group) - bulk = 0; - if(!ret && !thrmgr_group_dispatch(dup_conn->thrpool, dup_conn->group, dup_conn, bulk)) { - logg("!thread dispatch failed\n"); - ret = -2; + bulk = 0; + if (!ret && !thrmgr_group_dispatch(dup_conn->thrpool, dup_conn->group, dup_conn, bulk)) { + logg("!thread dispatch failed\n"); + ret = -2; } if (ret) { - cl_engine_free(dup_conn->engine); - free(dup_conn); + cl_engine_free(dup_conn->engine); + free(dup_conn); } return ret; } @@ -489,15 +487,15 @@ uint32_t ver; ver = cl_engine_get_num(engine, CL_ENGINE_DB_VERSION, NULL); - if(ver) { - char timestr[32]; - const char *tstr; - time_t t; - t = cl_engine_get_num(engine, CL_ENGINE_DB_TIME, NULL); - tstr = cli_ctime(&t, timestr, sizeof(timestr)); - /* cut trailing \n */ - timestr[strlen(tstr)-1] = '\0'; - return mdprintf(desc, "ClamAV %s/%u/%s%c", get_version(), (unsigned int) ver, tstr, term); + if (ver) { + char timestr[32]; + const char *tstr; + time_t t; + t = cl_engine_get_num(engine, CL_ENGINE_DB_TIME, NULL); + tstr = cli_ctime(&t, timestr, sizeof(timestr)); + /* cut trailing \n */ + timestr[strlen(tstr) - 1] = '\0'; + return mdprintf(desc, "ClamAV %s/%u/%s%c", get_version(), (unsigned int)ver, tstr, term); } return mdprintf(desc, "ClamAV %s%c", get_version(), term); } @@ -506,17 +504,17 @@ { unsigned i, n; const char *engine_ver = cl_retver(); - const char *clamd_ver = get_version(); + const char *clamd_ver = get_version(); if (strcmp(engine_ver, clamd_ver)) { - mdprintf(desc, "ENGINE VERSION MISMATCH: %s != %s. ERROR%c", - engine_ver, clamd_ver, term); - return; + mdprintf(desc, "ENGINE VERSION MISMATCH: %s != %s. ERROR%c", + engine_ver, clamd_ver, term); + return; } print_ver(desc, '|', engine); mdprintf(desc, " COMMANDS:"); - n = sizeof(commands)/sizeof(commands[0]); - for (i=0;isd; - char term = conn->term; + int desc = conn->sd; + char term = conn->term; const struct cl_engine *engine = conn->engine; /* execute commands that can be executed quickly on the recvloop thread, * these must: @@ -540,105 +538,100 @@ * - send of atomic message is allowed. * Dispatch other commands */ if (conn->group) { - switch (cmd) { - case COMMAND_FILDES: - case COMMAND_SCAN: - case COMMAND_END: - case COMMAND_INSTREAM: - case COMMAND_INSTREAMSCAN: - case COMMAND_VERSION: - case COMMAND_PING: - case COMMAND_STATS: - case COMMAND_COMMANDS: - /* These commands are accepted inside IDSESSION */ - break; - default: - /* these commands are not recognized inside an IDSESSION */ - conn_reply_error(conn, "Command invalid inside IDSESSION."); - logg("$SESSION: command is not valid inside IDSESSION: %d\n", cmd); - conn->group = NULL; - return 1; - } + switch (cmd) { + case COMMAND_FILDES: + case COMMAND_SCAN: + case COMMAND_END: + case COMMAND_INSTREAM: + case COMMAND_INSTREAMSCAN: + case COMMAND_VERSION: + case COMMAND_PING: + case COMMAND_STATS: + case COMMAND_COMMANDS: + /* These commands are accepted inside IDSESSION */ + break; + default: + /* these commands are not recognized inside an IDSESSION */ + conn_reply_error(conn, "Command invalid inside IDSESSION."); + logg("$SESSION: command is not valid inside IDSESSION: %d\n", cmd); + conn->group = NULL; + return 1; + } } switch (cmd) { - case COMMAND_SHUTDOWN: - pthread_mutex_lock(&exit_mutex); - progexit = 1; - pthread_mutex_unlock(&exit_mutex); - return 1; - case COMMAND_RELOAD: - pthread_mutex_lock(&reload_mutex); - reload = 1; - pthread_mutex_unlock(&reload_mutex); - mdprintf(desc, "RELOADING%c", term); - /* we set reload flag, and we'll reload before closing the + case COMMAND_SHUTDOWN: + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + return 1; + case COMMAND_RELOAD: + pthread_mutex_lock(&reload_mutex); + reload = 1; + pthread_mutex_unlock(&reload_mutex); + mdprintf(desc, "RELOADING%c", term); + /* we set reload flag, and we'll reload before closing the * connection */ - return 1; - case COMMAND_PING: - if (conn->group) - mdprintf(desc, "%u: PONG%c", conn->id, term); - else - mdprintf(desc, "PONG%c", term); - return conn->group ? 0 : 1; - case COMMAND_VERSION: - { - if (conn->group) - mdprintf(desc, "%u: ", conn->id); - print_ver(desc, conn->term, engine); - return conn->group ? 0 : 1; - } - case COMMAND_COMMANDS: - { - if (conn->group) - mdprintf(desc, "%u: ", conn->id); - print_commands(desc, conn->term, engine); - return conn->group ? 0 : 1; - } - case COMMAND_DETSTATSCLEAR: - { - /* TODO: tell client this command has been removed */ - return 1; - } - case COMMAND_DETSTATS: - { - /* TODO: tell client this command has been removed */ - return 1; - } - case COMMAND_INSTREAM: - { - int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd); - if (rc != CL_SUCCESS) - return rc; - conn->quota = optget(conn->opts, "StreamMaxLength")->numarg; - conn->mode = MODE_STREAM; - return 0; - } - case COMMAND_STREAM: - case COMMAND_MULTISCAN: - case COMMAND_CONTSCAN: - case COMMAND_STATS: - case COMMAND_FILDES: - case COMMAND_SCAN: - case COMMAND_INSTREAMSCAN: - case COMMAND_ALLMATCHSCAN: - return dispatch_command(conn, cmd, argument); - case COMMAND_IDSESSION: - conn->group = thrmgr_group_new(); - if (!conn->group) - return CL_EMEM; - return 0; - case COMMAND_END: - if (!conn->group) { - /* end without idsession? */ - conn_reply_single(conn, NULL, "UNKNOWN COMMAND"); - return 1; - } - /* need to close connection if we were last in group */ - return 1; - /*case COMMAND_UNKNOWN:*/ - default: - conn_reply_single(conn, NULL, "UNKNOWN COMMAND"); - return 1; + return 1; + case COMMAND_PING: + if (conn->group) + mdprintf(desc, "%u: PONG%c", conn->id, term); + else + mdprintf(desc, "PONG%c", term); + return conn->group ? 0 : 1; + case COMMAND_VERSION: { + if (conn->group) + mdprintf(desc, "%u: ", conn->id); + print_ver(desc, conn->term, engine); + return conn->group ? 0 : 1; + } + case COMMAND_COMMANDS: { + if (conn->group) + mdprintf(desc, "%u: ", conn->id); + print_commands(desc, conn->term, engine); + return conn->group ? 0 : 1; + } + case COMMAND_DETSTATSCLEAR: { + /* TODO: tell client this command has been removed */ + return 1; + } + case COMMAND_DETSTATS: { + /* TODO: tell client this command has been removed */ + return 1; + } + case COMMAND_INSTREAM: { + int rc = cli_gentempfd(optget(conn->opts, "TemporaryDirectory")->strarg, &conn->filename, &conn->scanfd); + if (rc != CL_SUCCESS) + return rc; + conn->quota = optget(conn->opts, "StreamMaxLength")->numarg; + conn->mode = MODE_STREAM; + return 0; + } + case COMMAND_STREAM: + case COMMAND_MULTISCAN: + case COMMAND_CONTSCAN: + case COMMAND_STATS: + case COMMAND_FILDES: + case COMMAND_SCAN: + case COMMAND_INSTREAMSCAN: + case COMMAND_ALLMATCHSCAN: + return dispatch_command(conn, cmd, argument); + case COMMAND_IDSESSION: + conn->group = thrmgr_group_new(); + if (!conn->group) + return CL_EMEM; + return 0; + case COMMAND_END: + if (!conn->group) { + /* end without idsession? */ + conn_reply_single(conn, NULL, "UNKNOWN COMMAND"); + return 1; + } + /* need to close connection if we were last in group */ + return 1; + /*case COMMAND_UNKNOWN:*/ + default: + conn_reply_single(conn, NULL, "UNKNOWN COMMAND"); + return 1; } } diff -Nru clamav-0.101.4+dfsg/clamd/session.h clamav-0.102.1+dfsg/clamd/session.h --- clamav-0.101.4+dfsg/clamd/session.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/session.h 2019-11-20 04:42:24.000000000 +0000 @@ -22,7 +22,6 @@ #ifndef __SESSION_H #define __SESSION_H - #define CMD1 "SCAN" /* #define CMD2 "RAWSCAN" */ #define CMD3 "QUIT" /* deprecated */ @@ -46,13 +45,17 @@ #define CMD21 "ALLMATCHSCAN" +#define CMD22 "GET / HTTP/1.1" +#define CMD23 "GET / HTTP/2" +#define CMD24 "" + #include "libclamav/clamav.h" #include "shared/optparser.h" #include "server.h" #include "others.h" enum commands { - COMMAND_UNKNOWN = 0, + COMMAND_UNKNOWN = 0, COMMAND_SHUTDOWN = 1, COMMAND_RELOAD, COMMAND_END, @@ -74,7 +77,10 @@ /* internal commands */ COMMAND_MULTISCANFILE, COMMAND_INSTREAMSCAN, - COMMAND_ALLMATCHSCAN + COMMAND_ALLMATCHSCAN, + COMMAND_SYNACK, + COMMAND_ACK, + COMMAND_GOPHER }; typedef struct client_conn_tag { diff -Nru clamav-0.101.4+dfsg/clamd/tcpserver.c clamav-0.102.1+dfsg/clamd/tcpserver.c --- clamav-0.101.4+dfsg/clamd/tcpserver.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/tcpserver.c 2019-11-20 04:42:24.000000000 +0000 @@ -29,7 +29,7 @@ #ifdef HAVE_UNISTD_H #include #endif -#ifndef _WIN32 +#ifndef _WIN32 #include #include #include @@ -57,44 +57,34 @@ char *estr, port[10]; int yes = 1; int res; - unsigned int i=0; - int num_fd; + unsigned int i = 0; + int num_fd; sockets = *lsockets; num_fd = sd_listen_fds(0); - if (num_fd > 2) - { + if (num_fd > 2) { logg("!TCP: Received more than two file descriptors from systemd.\n"); return -1; - } - else if (num_fd > 0) - { + } else if (num_fd > 0) { /* use socket passed by systemd */ int i; - for(i = 0; i < num_fd; i += 1) - { + for (i = 0; i < num_fd; i += 1) { sockfd = SD_LISTEN_FDS_START + i; - if (sd_is_socket(sockfd, AF_INET, SOCK_STREAM, 1) == 1) - { + if (sd_is_socket(sockfd, AF_INET, SOCK_STREAM, 1) == 1) { /* correct socket */ logg("#TCP: Received AF_INET SOCK_STREAM socket from systemd.\n"); break; - } - else if (sd_is_socket(sockfd, AF_INET6, SOCK_STREAM, 1) == 1) - { + } else if (sd_is_socket(sockfd, AF_INET6, SOCK_STREAM, 1) == 1) { /* correct socket */ logg("#TCP: Received AF_INET6 SOCK_STREAM socket from systemd.\n"); break; - } - else - { + } else { /* wrong socket */ sockfd = -2; } } - if (sockfd == -2) - { + if (sockfd == -2) { logg("#TCP: No tcp AF_INET/AF_INET6 SOCK_STREAM socket received from systemd.\n"); return -2; } @@ -115,9 +105,9 @@ snprintf(port, sizeof(port), "%lld", optget(opts, "TCPSocket")->numarg); memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; @@ -131,7 +121,7 @@ for (p = info; p != NULL; p = p->ai_next, i++) { t = realloc(sockets, sizeof(int) * (*nlsockets + 1)); if (!(t)) { - for (i=0; i < *nlsockets; i++) + for (i = 0; i < *nlsockets; i++) close(sockets[i]); return -1; @@ -144,7 +134,7 @@ continue; } - if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)) == -1) { + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)) == -1) { logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno)); } @@ -158,20 +148,20 @@ #ifdef HAVE_GETNAMEINFO if ((res = getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof(host), - serv, sizeof(serv), NI_NUMERICHOST|NI_NUMERICSERV))) { + serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV))) { logg("!TCP: getnameinfo failed: %s\n", gai_strerror(res)); host[0] = '\0'; serv[0] = '\0'; } #else - if (ipaddr) { - strncpy(host, ipaddr, sizeof(host)); - host[sizeof(host)-1] = '\0'; - } else - host[0] = '\0'; + if (ipaddr) { + strncpy(host, ipaddr, sizeof(host)); + host[sizeof(host) - 1] = '\0'; + } else + host[0] = '\0'; snprintf(serv, sizeof(serv), "%u", (unsigned int)(optget(opts, "TCPSocket")->numarg)); #endif - if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { + if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) { estr = strerror(errno); logg("!TCP: Cannot bind to [%s]:%s: %s\n", host, serv, estr); closesocket(sockfd); @@ -183,7 +173,7 @@ backlog = optget(opts, "MaxConnectionQueueLength")->numarg; logg("#TCP: Setting connection queue length to %d\n", backlog); - if(listen(sockfd, backlog) == -1) { + if (listen(sockfd, backlog) == -1) { estr = strerror(errno); logg("!TCP: Cannot listen on [%s]:%s: %s\n", host, serv, estr); closesocket(sockfd); diff -Nru clamav-0.101.4+dfsg/clamd/thrmgr.c clamav-0.102.1+dfsg/clamd/thrmgr.c --- clamav-0.101.4+dfsg/clamd/thrmgr.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/thrmgr.c 2019-11-20 04:42:24.000000000 +0000 @@ -44,450 +44,448 @@ #endif /* BSD and HP-UX need a bigger stacksize than the system default */ -#if defined (C_BSD) || defined (C_HPUX) || defined(C_AIX) || (defined(C_LINUX) && !defined(__GLIBC__)) +#if defined(C_BSD) || defined(C_HPUX) || defined(C_AIX) || (defined(C_LINUX) && !defined(__GLIBC__)) #define C_BIGSTACK 1 #endif static work_queue_t *work_queue_new(void) { - work_queue_t *work_q; + work_queue_t *work_q; - work_q = (work_queue_t *) malloc(sizeof(work_queue_t)); - if (!work_q) { - return NULL; - } - - work_q->head = work_q->tail = NULL; - work_q->item_count = 0; - work_q->popped = 0; - return work_q; + work_q = (work_queue_t *)malloc(sizeof(work_queue_t)); + if (!work_q) { + return NULL; + } + + work_q->head = work_q->tail = NULL; + work_q->item_count = 0; + work_q->popped = 0; + return work_q; } static int work_queue_add(work_queue_t *work_q, void *data) { - work_item_t *work_item; + work_item_t *work_item; - if (!work_q) { - return FALSE; - } - work_item = (work_item_t *) malloc(sizeof(work_item_t)); - if (!work_item) { - return FALSE; - } - - work_item->next = NULL; - work_item->data = data; - gettimeofday(&(work_item->time_queued), NULL); - - if (work_q->head == NULL) { - work_q->head = work_q->tail = work_item; - work_q->item_count = 1; - } else { - work_q->tail->next = work_item; - work_q->tail = work_item; - work_q->item_count++; - } - return TRUE; + if (!work_q) { + return FALSE; + } + work_item = (work_item_t *)malloc(sizeof(work_item_t)); + if (!work_item) { + return FALSE; + } + + work_item->next = NULL; + work_item->data = data; + gettimeofday(&(work_item->time_queued), NULL); + + if (work_q->head == NULL) { + work_q->head = work_q->tail = work_item; + work_q->item_count = 1; + } else { + work_q->tail->next = work_item; + work_q->tail = work_item; + work_q->item_count++; + } + return TRUE; } static void *work_queue_pop(work_queue_t *work_q) { - work_item_t *work_item; - void *data; + work_item_t *work_item; + void *data; - if (!work_q || !work_q->head) { - return NULL; - } - work_item = work_q->head; - data = work_item->data; - work_q->head = work_item->next; - if (work_q->head == NULL) { - work_q->tail = NULL; - } - free(work_item); - work_q->item_count--; - return data; + if (!work_q || !work_q->head) { + return NULL; + } + work_item = work_q->head; + data = work_item->data; + work_q->head = work_item->next; + if (work_q->head == NULL) { + work_q->tail = NULL; + } + free(work_item); + work_q->item_count--; + return data; } static struct threadpool_list { - threadpool_t *pool; - struct threadpool_list *nxt; -} *pools = NULL; + threadpool_t *pool; + struct threadpool_list *nxt; +} *pools = NULL; static pthread_mutex_t pools_lock = PTHREAD_MUTEX_INITIALIZER; static void add_topools(threadpool_t *t) { - struct threadpool_list *new = malloc(sizeof(*new)); - if(!new) { - logg("!Unable to add threadpool to list\n"); - return; - } - new->pool = t; - pthread_mutex_lock(&pools_lock); - new->nxt = pools; - pools = new; - pthread_mutex_unlock(&pools_lock); + struct threadpool_list *new = malloc(sizeof(*new)); + if (!new) { + logg("!Unable to add threadpool to list\n"); + return; + } + new->pool = t; + pthread_mutex_lock(&pools_lock); + new->nxt = pools; + pools = new; + pthread_mutex_unlock(&pools_lock); } static void remove_frompools(threadpool_t *t) { - struct threadpool_list *l, *prev; - struct task_desc *desc; - pthread_mutex_lock(&pools_lock); - prev = NULL; - l = pools; - while(l && l->pool != t) { - prev = l; - l = l->nxt; - } - if(!l) { + struct threadpool_list *l, *prev; + struct task_desc *desc; + pthread_mutex_lock(&pools_lock); + prev = NULL; + l = pools; + while (l && l->pool != t) { + prev = l; + l = l->nxt; + } + if (!l) { pthread_mutex_unlock(&pools_lock); - return; + return; + } + if (prev) + prev->nxt = l->nxt; + if (l == pools) + pools = l->nxt; + free(l); + desc = t->tasks; + while (desc) { + struct task_desc *q = desc; + desc = desc->nxt; + free(q); } - if(prev) - prev->nxt = l->nxt; - if(l == pools) - pools = l->nxt; - free(l); - desc = t->tasks; - while(desc) { - struct task_desc *q = desc; - desc = desc->nxt; - free(q); - } - t->tasks = NULL; - pthread_mutex_unlock(&pools_lock); + t->tasks = NULL; + pthread_mutex_unlock(&pools_lock); } static void print_queue(int f, work_queue_t *queue, struct timeval *tv_now) { - long umin=LONG_MAX, umax=0, usum=0; + long umin = LONG_MAX, umax = 0, usum = 0; unsigned invalids = 0, cnt = 0; work_item_t *q; - if(!queue->head) - return; - for(q=queue->head;q;q=q->next) { - long delta; - delta = tv_now->tv_usec - q->time_queued.tv_usec; - delta += (tv_now->tv_sec - q->time_queued.tv_sec)*1000000; - if(delta < 0) { - invalids++; - continue; - } - if(delta > umax) - umax = delta; - if(delta < umin) - umin = delta; - usum += delta; - ++cnt; - } - mdprintf(f," min_wait: %.6f max_wait: %.6f avg_wait: %.6f", - umin/1e6, umax/1e6, usum /(1e6*cnt)); - if(invalids) - mdprintf(f," (INVALID timestamps: %u)", invalids); - if(cnt + invalids != (unsigned)queue->item_count) - mdprintf(f," (ERROR: %u != %u)", cnt + invalids, - (unsigned)queue->item_count); + if (!queue->head) + return; + for (q = queue->head; q; q = q->next) { + long delta; + delta = tv_now->tv_usec - q->time_queued.tv_usec; + delta += (tv_now->tv_sec - q->time_queued.tv_sec) * 1000000; + if (delta < 0) { + invalids++; + continue; + } + if (delta > umax) + umax = delta; + if (delta < umin) + umin = delta; + usum += delta; + ++cnt; + } + mdprintf(f, " min_wait: %.6f max_wait: %.6f avg_wait: %.6f", + umin / 1e6, umax / 1e6, usum / (1e6 * cnt)); + if (invalids) + mdprintf(f, " (INVALID timestamps: %u)", invalids); + if (cnt + invalids != (unsigned)queue->item_count) + mdprintf(f, " (ERROR: %u != %u)", cnt + invalids, + (unsigned)queue->item_count); } int thrmgr_printstats(int f, char term) { - struct threadpool_list *l; - unsigned cnt, pool_cnt = 0; - size_t pool_used = 0, pool_total = 0, seen_cnt = 0, error_flag = 0; - float mem_heap = 0, mem_mmap = 0, mem_used = 0, mem_free = 0, mem_releasable = 0; - const struct cl_engine **seen = NULL; - int has_libc_memstats = 0; - - pthread_mutex_lock(&pools_lock); - for(cnt=0,l=pools;l;l=l->nxt) cnt++; - mdprintf(f,"POOLS: %u\n\n", cnt); - for(l= pools;l && !error_flag;l = l->nxt) { - threadpool_t *pool = l->pool; - const char *state; - struct timeval tv_now; - struct task_desc *task; - cnt = 0; - - if(!pool) { - mdprintf(f,"NULL\n\n"); - continue; - } - /* now we can access desc->, knowing that they won't get freed + struct threadpool_list *l; + unsigned cnt, pool_cnt = 0; + size_t pool_used = 0, pool_total = 0, seen_cnt = 0, error_flag = 0; + float mem_heap = 0, mem_mmap = 0, mem_used = 0, mem_free = 0, mem_releasable = 0; + const struct cl_engine **seen = NULL; + int has_libc_memstats = 0; + + pthread_mutex_lock(&pools_lock); + for (cnt = 0, l = pools; l; l = l->nxt) cnt++; + mdprintf(f, "POOLS: %u\n\n", cnt); + for (l = pools; l && !error_flag; l = l->nxt) { + threadpool_t *pool = l->pool; + const char *state; + struct timeval tv_now; + struct task_desc *task; + cnt = 0; + + if (!pool) { + mdprintf(f, "NULL\n\n"); + continue; + } + /* now we can access desc->, knowing that they won't get freed * because the other tasks can't quit while pool_mutex is taken */ - switch(pool->state) { - case POOL_INVALID: - state = "INVALID"; - break; - case POOL_VALID: - state = "VALID"; - break; - case POOL_EXIT: - state = "EXIT"; - break; - default: - state = "??"; - break; - } - mdprintf(f, "STATE: %s %s\n", state, l->nxt ? "" : "PRIMARY"); - mdprintf(f, "THREADS: live %u idle %u max %u idle-timeout %u\n" - ,pool->thr_alive, pool->thr_idle, pool->thr_max, - pool->idle_timeout); - /* TODO: show both queues */ - mdprintf(f,"QUEUE: %u items", pool->single_queue->item_count + pool->bulk_queue->item_count); - gettimeofday(&tv_now, NULL); - print_queue(f, pool->bulk_queue, &tv_now); - print_queue(f, pool->single_queue, &tv_now); - mdprintf(f, "\n"); - for(task = pool->tasks; task; task = task->nxt) { - double delta; - size_t used, total; - - delta = tv_now.tv_usec - task->tv.tv_usec; - delta += (tv_now.tv_sec - task->tv.tv_sec)*1000000.0; - mdprintf(f,"\t%s %f %s\n", - task->command ? task->command : "N/A", - delta/1e6, - task->filename ? task->filename:""); - if (task->engine) { - /* we usually have at most 2 engines so a linear + switch (pool->state) { + case POOL_INVALID: + state = "INVALID"; + break; + case POOL_VALID: + state = "VALID"; + break; + case POOL_EXIT: + state = "EXIT"; + break; + default: + state = "??"; + break; + } + mdprintf(f, "STATE: %s %s\n", state, l->nxt ? "" : "PRIMARY"); + mdprintf(f, "THREADS: live %u idle %u max %u idle-timeout %u\n", pool->thr_alive, pool->thr_idle, pool->thr_max, + pool->idle_timeout); + /* TODO: show both queues */ + mdprintf(f, "QUEUE: %u items", pool->single_queue->item_count + pool->bulk_queue->item_count); + gettimeofday(&tv_now, NULL); + print_queue(f, pool->bulk_queue, &tv_now); + print_queue(f, pool->single_queue, &tv_now); + mdprintf(f, "\n"); + for (task = pool->tasks; task; task = task->nxt) { + double delta; + size_t used, total; + + delta = tv_now.tv_usec - task->tv.tv_usec; + delta += (tv_now.tv_sec - task->tv.tv_sec) * 1000000.0; + mdprintf(f, "\t%s %f %s\n", + task->command ? task->command : "N/A", + delta / 1e6, + task->filename ? task->filename : ""); + if (task->engine) { + /* we usually have at most 2 engines so a linear * search is good enough */ - size_t i; - for (i=0;iengine) - break; - } - /* we need to count the memusage from the same + size_t i; + for (i = 0; i < seen_cnt; i++) { + if (seen[i] == task->engine) + break; + } + /* we need to count the memusage from the same * engine only once */ - if (i == seen_cnt) { - const struct cl_engine **s; - /* new engine */ - ++seen_cnt; - s = realloc(seen, seen_cnt * sizeof(*seen)); - if (!s) { - error_flag = 1; - break; - } - seen = s; - seen[seen_cnt - 1] = task->engine; - - if (mpool_getstats(task->engine, &used, &total) != -1) { - pool_used += used; - pool_total += total; - pool_cnt++; - } - } - } - } - mdprintf(f,"\n"); - } - free(seen); + if (i == seen_cnt) { + const struct cl_engine **s; + /* new engine */ + ++seen_cnt; + s = realloc(seen, seen_cnt * sizeof(*seen)); + if (!s) { + error_flag = 1; + break; + } + seen = s; + seen[seen_cnt - 1] = task->engine; + + if (MPOOL_GETSTATS(task->engine, &used, &total) != -1) { + pool_used += used; + pool_total += total; + pool_cnt++; + } + } + } + } + mdprintf(f, "\n"); + } + free(seen); #ifdef HAVE_MALLINFO - { - struct mallinfo inf = mallinfo(); - mem_heap = inf.arena/(1024*1024.0); - mem_mmap = inf.hblkhd/(1024*1024.0); - mem_used = (inf.usmblks + inf.uordblks)/(1024*1024.0); - mem_free = (inf.fsmblks + inf.fordblks)/(1024*1024.0); - mem_releasable = inf.keepcost/(1024*1024.0); - has_libc_memstats=1; - } + { + struct mallinfo inf = mallinfo(); + mem_heap = inf.arena / (1024 * 1024.0); + mem_mmap = inf.hblkhd / (1024 * 1024.0); + mem_used = (inf.usmblks + inf.uordblks) / (1024 * 1024.0); + mem_free = (inf.fsmblks + inf.fordblks) / (1024 * 1024.0); + mem_releasable = inf.keepcost / (1024 * 1024.0); + has_libc_memstats = 1; + } #endif - if (error_flag) { - mdprintf(f, "ERROR: error encountered while formatting statistics\n"); - } else { - if (has_libc_memstats) - mdprintf(f,"MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM pools %u pools_used %.3fM pools_total %.3fM\n", - mem_heap, mem_mmap, mem_used, mem_free, mem_releasable, pool_cnt, - pool_used/(1024*1024.0), pool_total/(1024*1024.0)); - else - mdprintf(f,"MEMSTATS: heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %.3fM pools_total %.3fM\n", - pool_cnt, pool_used/(1024*1024.0), pool_total/(1024*1024.0)); - } - mdprintf(f,"END%c", term); - pthread_mutex_unlock(&pools_lock); - return 0; + if (error_flag) { + mdprintf(f, "ERROR: error encountered while formatting statistics\n"); + } else { + if (has_libc_memstats) + mdprintf(f, "MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM pools %u pools_used %.3fM pools_total %.3fM\n", + mem_heap, mem_mmap, mem_used, mem_free, mem_releasable, pool_cnt, + pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); + else + mdprintf(f, "MEMSTATS: heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %.3fM pools_total %.3fM\n", + pool_cnt, pool_used / (1024 * 1024.0), pool_total / (1024 * 1024.0)); + } + mdprintf(f, "END%c", term); + pthread_mutex_unlock(&pools_lock); + return 0; } void thrmgr_destroy(threadpool_t *threadpool) { - if (!threadpool) { - return; - } - if (pthread_mutex_lock(&threadpool->pool_mutex) != 0) { - logg("!Mutex lock failed\n"); - exit(-1); - } - if(threadpool->state != POOL_VALID) { - if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0) { - logg("!Mutex unlock failed\n"); - exit(-1); - } - return; - } - threadpool->state = POOL_EXIT; - - /* wait for threads to exit */ - if (threadpool->thr_alive > 0) { - if (pthread_cond_broadcast(&(threadpool->pool_cond)) != 0) { - pthread_mutex_unlock(&threadpool->pool_mutex); - return; - } - } - while (threadpool->thr_alive > 0) { - if (pthread_cond_wait (&threadpool->pool_cond, &threadpool->pool_mutex) != 0) { - pthread_mutex_unlock(&threadpool->pool_mutex); - return; - } - } - remove_frompools(threadpool); - if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0) { - logg("!Mutex unlock failed\n"); - exit(-1); - } - - pthread_mutex_destroy(&(threadpool->pool_mutex)); - pthread_cond_destroy(&(threadpool->idle_cond)); - pthread_cond_destroy(&(threadpool->queueable_single_cond)); - pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_attr_destroy(&(threadpool->pool_attr)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return; + if (!threadpool) { + return; + } + if (pthread_mutex_lock(&threadpool->pool_mutex) != 0) { + logg("!Mutex lock failed\n"); + exit(-1); + } + if (threadpool->state != POOL_VALID) { + if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0) { + logg("!Mutex unlock failed\n"); + exit(-1); + } + return; + } + threadpool->state = POOL_EXIT; + + /* wait for threads to exit */ + if (threadpool->thr_alive > 0) { + if (pthread_cond_broadcast(&(threadpool->pool_cond)) != 0) { + pthread_mutex_unlock(&threadpool->pool_mutex); + return; + } + } + while (threadpool->thr_alive > 0) { + if (pthread_cond_wait(&threadpool->pool_cond, &threadpool->pool_mutex) != 0) { + pthread_mutex_unlock(&threadpool->pool_mutex); + return; + } + } + remove_frompools(threadpool); + if (pthread_mutex_unlock(&threadpool->pool_mutex) != 0) { + logg("!Mutex unlock failed\n"); + exit(-1); + } + + pthread_mutex_destroy(&(threadpool->pool_mutex)); + pthread_cond_destroy(&(threadpool->idle_cond)); + pthread_cond_destroy(&(threadpool->queueable_single_cond)); + pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_attr_destroy(&(threadpool->pool_attr)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return; } threadpool_t *thrmgr_new(int max_threads, int idle_timeout, int max_queue, void (*handler)(void *)) { - threadpool_t *threadpool; + threadpool_t *threadpool; #if defined(C_BIGSTACK) - size_t stacksize; + size_t stacksize; #endif - if (max_threads <= 0) { - return NULL; - } - - threadpool = (threadpool_t *) malloc(sizeof(threadpool_t)); - if (!threadpool) { - return NULL; - } - - threadpool->single_queue = work_queue_new(); - if (!threadpool->single_queue) { - free(threadpool); - return NULL; - } - threadpool->bulk_queue = work_queue_new(); - if (!threadpool->bulk_queue) { - free(threadpool->single_queue); - free(threadpool); - return NULL; - } - - threadpool->queue_max = max_queue; - - threadpool->thr_max = max_threads; - threadpool->thr_alive = 0; - threadpool->thr_idle = 0; - threadpool->thr_multiscan = 0; - threadpool->idle_timeout = idle_timeout; - threadpool->handler = handler; - threadpool->tasks = NULL; - - if(pthread_mutex_init(&(threadpool->pool_mutex), NULL)) { - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - if (pthread_cond_init(&(threadpool->pool_cond), NULL) != 0) { - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - if (pthread_cond_init(&(threadpool->queueable_single_cond), NULL) != 0) { - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - if (pthread_cond_init(&(threadpool->queueable_bulk_cond), NULL) != 0) { - pthread_cond_destroy(&(threadpool->queueable_single_cond)); - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - - if (pthread_cond_init(&(threadpool->idle_cond),NULL) != 0) { - pthread_cond_destroy(&(threadpool->queueable_single_cond)); - pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - if (pthread_attr_init(&(threadpool->pool_attr)) != 0) { - pthread_cond_destroy(&(threadpool->queueable_single_cond)); - pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); - pthread_cond_destroy(&(threadpool->idle_cond)); - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } - - if (pthread_attr_setdetachstate(&(threadpool->pool_attr), PTHREAD_CREATE_DETACHED) != 0) { - pthread_cond_destroy(&(threadpool->queueable_single_cond)); - pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); - pthread_attr_destroy(&(threadpool->pool_attr)); - pthread_cond_destroy(&(threadpool->idle_cond)); - pthread_cond_destroy(&(threadpool->pool_cond)); - pthread_mutex_destroy(&(threadpool->pool_mutex)); - free(threadpool->single_queue); - free(threadpool->bulk_queue); - free(threadpool); - return NULL; - } + if (max_threads <= 0) { + return NULL; + } + + threadpool = (threadpool_t *)malloc(sizeof(threadpool_t)); + if (!threadpool) { + return NULL; + } + + threadpool->single_queue = work_queue_new(); + if (!threadpool->single_queue) { + free(threadpool); + return NULL; + } + threadpool->bulk_queue = work_queue_new(); + if (!threadpool->bulk_queue) { + free(threadpool->single_queue); + free(threadpool); + return NULL; + } + + threadpool->queue_max = max_queue; + + threadpool->thr_max = max_threads; + threadpool->thr_alive = 0; + threadpool->thr_idle = 0; + threadpool->thr_multiscan = 0; + threadpool->idle_timeout = idle_timeout; + threadpool->handler = handler; + threadpool->tasks = NULL; + + if (pthread_mutex_init(&(threadpool->pool_mutex), NULL)) { + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_cond_init(&(threadpool->pool_cond), NULL) != 0) { + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_cond_init(&(threadpool->queueable_single_cond), NULL) != 0) { + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_cond_init(&(threadpool->queueable_bulk_cond), NULL) != 0) { + pthread_cond_destroy(&(threadpool->queueable_single_cond)); + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_cond_init(&(threadpool->idle_cond), NULL) != 0) { + pthread_cond_destroy(&(threadpool->queueable_single_cond)); + pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_attr_init(&(threadpool->pool_attr)) != 0) { + pthread_cond_destroy(&(threadpool->queueable_single_cond)); + pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); + pthread_cond_destroy(&(threadpool->idle_cond)); + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } + + if (pthread_attr_setdetachstate(&(threadpool->pool_attr), PTHREAD_CREATE_DETACHED) != 0) { + pthread_cond_destroy(&(threadpool->queueable_single_cond)); + pthread_cond_destroy(&(threadpool->queueable_bulk_cond)); + pthread_attr_destroy(&(threadpool->pool_attr)); + pthread_cond_destroy(&(threadpool->idle_cond)); + pthread_cond_destroy(&(threadpool->pool_cond)); + pthread_mutex_destroy(&(threadpool->pool_mutex)); + free(threadpool->single_queue); + free(threadpool->bulk_queue); + free(threadpool); + return NULL; + } #if defined(C_BIGSTACK) - pthread_attr_getstacksize(&(threadpool->pool_attr), &stacksize); - stacksize = stacksize + 64 * 1024; - if (stacksize < 1048576) /* at least 1MB please */ + pthread_attr_getstacksize(&(threadpool->pool_attr), &stacksize); + stacksize = stacksize + 64 * 1024; + if (stacksize < 1048576) /* at least 1MB please */ #if defined(C_HPUX) && defined(USE_MPOOL) - /* Set aside one cli_pagesize() for the stack's pthread header, + /* Set aside one cli_pagesize() for the stack's pthread header, * giving a 1M region to fit a 1M large-page */ - if(cli_getpagesize() < 1048576) - stacksize = 1048576 - cli_getpagesize(); - else + if (cli_getpagesize() < 1048576) + stacksize = 1048576 - cli_getpagesize(); + else #endif - stacksize = 1048576; - logg("Set stacksize to %lu\n", (unsigned long int) stacksize); - pthread_attr_setstacksize(&(threadpool->pool_attr), stacksize); + stacksize = 1048576; + logg("Set stacksize to %lu\n", (unsigned long int)stacksize); + pthread_attr_setstacksize(&(threadpool->pool_attr), stacksize); #endif - threadpool->state = POOL_VALID; + threadpool->state = POOL_VALID; - add_topools(threadpool); - return threadpool; + add_topools(threadpool); + return threadpool; } static pthread_key_t stats_tls_key; @@ -495,81 +493,80 @@ static void stats_tls_key_alloc(void) { - pthread_key_create(&stats_tls_key, NULL); + pthread_key_create(&stats_tls_key, NULL); } static const char *IDLE_TASK = "IDLE"; /* no mutex is needed, we are using thread local variable */ -void thrmgr_setactivetask(const char *filename, const char* cmd) +void thrmgr_setactivetask(const char *filename, const char *cmd) { - struct task_desc *desc; - pthread_once(&stats_tls_key_once, stats_tls_key_alloc); - desc = pthread_getspecific(stats_tls_key); - if(!desc) - return; - desc->filename = filename; - if(cmd) { - if(cmd == IDLE_TASK && desc->command == cmd) - return; - desc->command = cmd; - gettimeofday(&desc->tv, NULL); - } + struct task_desc *desc; + pthread_once(&stats_tls_key_once, stats_tls_key_alloc); + desc = pthread_getspecific(stats_tls_key); + if (!desc) + return; + desc->filename = filename; + if (cmd) { + if (cmd == IDLE_TASK && desc->command == cmd) + return; + desc->command = cmd; + gettimeofday(&desc->tv, NULL); + } } void thrmgr_setactiveengine(const struct cl_engine *engine) { - struct task_desc *desc; - pthread_once(&stats_tls_key_once, stats_tls_key_alloc); - desc = pthread_getspecific(stats_tls_key); - if(!desc) - return; - desc->engine = engine; + struct task_desc *desc; + pthread_once(&stats_tls_key_once, stats_tls_key_alloc); + desc = pthread_getspecific(stats_tls_key); + if (!desc) + return; + desc->engine = engine; } /* thread pool mutex must be held on entry */ static void stats_init(threadpool_t *pool) { - struct task_desc *desc = calloc(1, sizeof(*desc)); - if(!desc) - return; - pthread_once(&stats_tls_key_once, stats_tls_key_alloc); - pthread_setspecific(stats_tls_key, desc); - if(!pool->tasks) - pool->tasks = desc; - else { - desc->nxt = pool->tasks; - pool->tasks->prv = desc; - pool->tasks = desc; - } + struct task_desc *desc = calloc(1, sizeof(*desc)); + if (!desc) + return; + pthread_once(&stats_tls_key_once, stats_tls_key_alloc); + pthread_setspecific(stats_tls_key, desc); + if (!pool->tasks) + pool->tasks = desc; + else { + desc->nxt = pool->tasks; + pool->tasks->prv = desc; + pool->tasks = desc; + } } /* thread pool mutex must be held on entry */ static void stats_destroy(threadpool_t *pool) { - struct task_desc *desc = pthread_getspecific(stats_tls_key); - if(!desc) - return; - pthread_mutex_lock(&pools_lock); - if(desc->prv) - desc->prv->nxt = desc->nxt; - if(desc->nxt) - desc->nxt->prv = desc->prv; - if(pool->tasks == desc) - pool->tasks = desc->nxt; - free(desc); - pthread_setspecific(stats_tls_key, NULL); - pthread_mutex_unlock(&pools_lock); + struct task_desc *desc = pthread_getspecific(stats_tls_key); + if (!desc) + return; + pthread_mutex_lock(&pools_lock); + if (desc->prv) + desc->prv->nxt = desc->nxt; + if (desc->nxt) + desc->nxt->prv = desc->prv; + if (pool->tasks == desc) + pool->tasks = desc->nxt; + free(desc); + pthread_setspecific(stats_tls_key, NULL); + pthread_mutex_unlock(&pools_lock); } static inline int thrmgr_contended(threadpool_t *pool, int bulk) { /* don't allow bulk items to exceed 50% of queue, so that * non-bulk items get a chance to be in the queue */ - if (bulk && pool->bulk_queue->item_count >= pool->queue_max/2) - return 1; - return pool->bulk_queue->item_count + pool->single_queue->item_count - + pool->thr_alive - pool->thr_idle >= pool->queue_max; + if (bulk && pool->bulk_queue->item_count >= pool->queue_max / 2) + return 1; + return pool->bulk_queue->item_count + pool->single_queue->item_count + pool->thr_alive - pool->thr_idle >= pool->queue_max; } /* when both queues have tasks, it will pick 4 items from the single queue, @@ -585,172 +582,170 @@ int ratio; if (pool->single_queue->popped < SINGLE_BULK_RATIO) { - first = pool->single_queue; - second = pool->bulk_queue; - ratio = SINGLE_BULK_RATIO; + first = pool->single_queue; + second = pool->bulk_queue; + ratio = SINGLE_BULK_RATIO; } else { - second = pool->single_queue; - first = pool->bulk_queue; - ratio = SINGLE_BULK_SUM - SINGLE_BULK_RATIO; + second = pool->single_queue; + first = pool->bulk_queue; + ratio = SINGLE_BULK_SUM - SINGLE_BULK_RATIO; } task = work_queue_pop(first); if (task) { - if (++first->popped == ratio) - second->popped = 0; + if (++first->popped == ratio) + second->popped = 0; } else { - task = work_queue_pop(second); - if (task) { - if (++second->popped == ratio) - first->popped = 0; - } + task = work_queue_pop(second); + if (task) { + if (++second->popped == ratio) + first->popped = 0; + } } if (!thrmgr_contended(pool, 0)) { - logg("$THRMGR: queue (single) crossed low threshold -> signaling\n"); - pthread_cond_signal(&pool->queueable_single_cond); + logg("$THRMGR: queue (single) crossed low threshold -> signaling\n"); + pthread_cond_signal(&pool->queueable_single_cond); } if (!thrmgr_contended(pool, 1)) { - logg("$THRMGR: queue (bulk) crossed low threshold -> signaling\n"); - pthread_cond_signal(&pool->queueable_bulk_cond); + logg("$THRMGR: queue (bulk) crossed low threshold -> signaling\n"); + pthread_cond_signal(&pool->queueable_bulk_cond); } return task; } - static void *thrmgr_worker(void *arg) { - threadpool_t *threadpool = (threadpool_t *) arg; - void *job_data; - int retval, must_exit = FALSE, stats_inited = FALSE; - struct timespec timeout; - - /* loop looking for work */ - for (;;) { - if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { - logg("!Fatal: mutex lock failed\n"); - exit(-2); - } - if(!stats_inited) { - stats_init(threadpool); - stats_inited = TRUE; - } - thrmgr_setactiveengine(NULL); - thrmgr_setactivetask(NULL, IDLE_TASK); - timeout.tv_sec = time(NULL) + threadpool->idle_timeout; - timeout.tv_nsec = 0; - threadpool->thr_idle++; - while (((job_data=thrmgr_pop(threadpool)) == NULL) - && (threadpool->state != POOL_EXIT)) { - /* Sleep, awaiting wakeup */ - pthread_cond_signal(&threadpool->idle_cond); - retval = pthread_cond_timedwait(&(threadpool->pool_cond), - &(threadpool->pool_mutex), &timeout); - if (retval == ETIMEDOUT) { - must_exit = TRUE; - break; - } - } - threadpool->thr_idle--; - if (threadpool->state == POOL_EXIT) { - must_exit = TRUE; - } - - if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { - logg("!Fatal: mutex unlock failed\n"); - exit(-2); - } - if (job_data) { - threadpool->handler(job_data); - } else if (must_exit) { - break; - } - } - if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { - /* Fatal error */ - logg("!Fatal: mutex lock failed\n"); - exit(-2); - } - threadpool->thr_alive--; - if (threadpool->thr_alive == 0) { - /* signal that all threads are finished */ - pthread_cond_broadcast(&threadpool->pool_cond); - } - stats_destroy(threadpool); - if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { - /* Fatal error */ - logg("!Fatal: mutex unlock failed\n"); - exit(-2); - } - return NULL; + threadpool_t *threadpool = (threadpool_t *)arg; + void *job_data; + int retval, must_exit = FALSE, stats_inited = FALSE; + struct timespec timeout; + + /* loop looking for work */ + for (;;) { + if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { + logg("!Fatal: mutex lock failed\n"); + exit(-2); + } + if (!stats_inited) { + stats_init(threadpool); + stats_inited = TRUE; + } + thrmgr_setactiveengine(NULL); + thrmgr_setactivetask(NULL, IDLE_TASK); + timeout.tv_sec = time(NULL) + threadpool->idle_timeout; + timeout.tv_nsec = 0; + threadpool->thr_idle++; + while (((job_data = thrmgr_pop(threadpool)) == NULL) && (threadpool->state != POOL_EXIT)) { + /* Sleep, awaiting wakeup */ + pthread_cond_signal(&threadpool->idle_cond); + retval = pthread_cond_timedwait(&(threadpool->pool_cond), + &(threadpool->pool_mutex), &timeout); + if (retval == ETIMEDOUT) { + must_exit = TRUE; + break; + } + } + threadpool->thr_idle--; + if (threadpool->state == POOL_EXIT) { + must_exit = TRUE; + } + + if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { + logg("!Fatal: mutex unlock failed\n"); + exit(-2); + } + if (job_data) { + threadpool->handler(job_data); + } else if (must_exit) { + break; + } + } + if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { + /* Fatal error */ + logg("!Fatal: mutex lock failed\n"); + exit(-2); + } + threadpool->thr_alive--; + if (threadpool->thr_alive == 0) { + /* signal that all threads are finished */ + pthread_cond_broadcast(&threadpool->pool_cond); + } + stats_destroy(threadpool); + if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { + /* Fatal error */ + logg("!Fatal: mutex unlock failed\n"); + exit(-2); + } + return NULL; } static int thrmgr_dispatch_internal(threadpool_t *threadpool, void *user_data, int bulk) { - int ret = TRUE; - pthread_t thr_id; + int ret = TRUE; + pthread_t thr_id; - if (!threadpool) { - return FALSE; - } - - /* Lock the threadpool */ - if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { - logg("!Mutex lock failed\n"); - return FALSE; - } - - do { - work_queue_t *queue; - pthread_cond_t *queueable_cond; - int items; - - if (threadpool->state != POOL_VALID) { - ret = FALSE; - break; - } - - if (bulk) { - queue = threadpool->bulk_queue; - queueable_cond = &threadpool->queueable_bulk_cond; - } else { - queue = threadpool->single_queue; - queueable_cond = &threadpool->queueable_single_cond; - } - - while (thrmgr_contended(threadpool, bulk)) { - logg("$THRMGR: contended, sleeping\n"); - pthread_cond_wait(queueable_cond, &threadpool->pool_mutex); - logg("$THRMGR: contended, woken\n"); - } - - if (!work_queue_add(queue, user_data)) { - ret = FALSE; - break; - } - - items = threadpool->single_queue->item_count + threadpool->bulk_queue->item_count; - if ((threadpool->thr_idle < items) && - (threadpool->thr_alive < threadpool->thr_max)) { - /* Start a new thread */ - if (pthread_create(&thr_id, &(threadpool->pool_attr), - thrmgr_worker, threadpool) != 0) { - logg("!pthread_create failed\n"); - } else { - threadpool->thr_alive++; - } - } - pthread_cond_signal(&(threadpool->pool_cond)); - - } while (0); - - if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { - logg("!Mutex unlock failed\n"); - return FALSE; - } - return ret; + if (!threadpool) { + return FALSE; + } + + /* Lock the threadpool */ + if (pthread_mutex_lock(&(threadpool->pool_mutex)) != 0) { + logg("!Mutex lock failed\n"); + return FALSE; + } + + do { + work_queue_t *queue; + pthread_cond_t *queueable_cond; + int items; + + if (threadpool->state != POOL_VALID) { + ret = FALSE; + break; + } + + if (bulk) { + queue = threadpool->bulk_queue; + queueable_cond = &threadpool->queueable_bulk_cond; + } else { + queue = threadpool->single_queue; + queueable_cond = &threadpool->queueable_single_cond; + } + + while (thrmgr_contended(threadpool, bulk)) { + logg("$THRMGR: contended, sleeping\n"); + pthread_cond_wait(queueable_cond, &threadpool->pool_mutex); + logg("$THRMGR: contended, woken\n"); + } + + if (!work_queue_add(queue, user_data)) { + ret = FALSE; + break; + } + + items = threadpool->single_queue->item_count + threadpool->bulk_queue->item_count; + if ((threadpool->thr_idle < items) && + (threadpool->thr_alive < threadpool->thr_max)) { + /* Start a new thread */ + if (pthread_create(&thr_id, &(threadpool->pool_attr), + thrmgr_worker, threadpool) != 0) { + logg("!pthread_create failed\n"); + } else { + threadpool->thr_alive++; + } + } + pthread_cond_signal(&(threadpool->pool_cond)); + + } while (0); + + if (pthread_mutex_unlock(&(threadpool->pool_mutex)) != 0) { + logg("!Mutex unlock failed\n"); + return FALSE; + } + return ret; } int thrmgr_dispatch(threadpool_t *threadpool, void *user_data) @@ -762,16 +757,16 @@ { int ret; if (group) { - pthread_mutex_lock(&group->mutex); - group->jobs++; - logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); - pthread_mutex_unlock(&group->mutex); + pthread_mutex_lock(&group->mutex); + group->jobs++; + logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); + pthread_mutex_unlock(&group->mutex); } if (!(ret = thrmgr_dispatch_internal(threadpool, user_data, bulk)) && group) { - pthread_mutex_lock(&group->mutex); - group->jobs--; - logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); - pthread_mutex_unlock(&group->mutex); + pthread_mutex_lock(&group->mutex); + group->jobs--; + logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); + pthread_mutex_unlock(&group->mutex); } return ret; } @@ -784,36 +779,36 @@ { int ret = 0; if (!group) { - /* there is no group, we are obviously the last one */ - return 1; + /* there is no group, we are obviously the last one */ + return 1; } pthread_mutex_lock(&group->mutex); logg("$THRMGR: group_finished: %p, %d\n", group, group->jobs); group->exit_total++; switch (exitc) { - case EXIT_OK: - group->exit_ok++; - break; - case EXIT_ERROR: - group->exit_error++; - break; - default: - break; + case EXIT_OK: + group->exit_ok++; + break; + case EXIT_ERROR: + group->exit_error++; + break; + default: + break; } if (group->jobs) { - if (!--group->jobs) { - ret = 1; - } else - logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); - if (group->jobs == 1) - pthread_cond_signal(&group->only); + if (!--group->jobs) { + ret = 1; + } else + logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); + if (group->jobs == 1) + pthread_cond_signal(&group->only); } pthread_mutex_unlock(&group->mutex); if (ret) { - logg("$THRMGR: group_finished: freeing %p\n", group); - pthread_mutex_destroy(&group->mutex); - pthread_cond_destroy(&group->only); - free(group); + logg("$THRMGR: group_finished: freeing %p\n", group); + pthread_mutex_destroy(&group->mutex); + pthread_cond_destroy(&group->only); + free(group); } return ret; } @@ -824,27 +819,27 @@ struct timespec timeout; pthread_mutex_lock(&group->mutex); while (group->jobs > 1) { - pthread_mutex_lock(&exit_mutex); - needexit = progexit; - pthread_mutex_unlock(&exit_mutex); - if (needexit) - break; - /* wake to check progexit */ - timeout.tv_sec = time(NULL) + 5; - timeout.tv_nsec = 0; - pthread_cond_timedwait(&group->only, &group->mutex, &timeout); + pthread_mutex_lock(&exit_mutex); + needexit = progexit; + pthread_mutex_unlock(&exit_mutex); + if (needexit) + break; + /* wake to check progexit */ + timeout.tv_sec = time(NULL) + 5; + timeout.tv_nsec = 0; + pthread_cond_timedwait(&group->only, &group->mutex, &timeout); } - *ok = group->exit_ok; + *ok = group->exit_ok; *error = group->exit_error + needexit; *total = group->exit_total; - if(!--group->jobs) - needfree = 1; + if (!--group->jobs) + needfree = 1; else - logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); + logg("$THRMGR: active jobs for %p: %d\n", group, group->jobs); pthread_mutex_unlock(&group->mutex); if (needfree) { - logg("$THRMGR: group finished freeing %p\n", group); - free(group); + logg("$THRMGR: group finished freeing %p\n", group); + free(group); } } @@ -854,19 +849,19 @@ group = malloc(sizeof(*group)); if (!group) - return NULL; - group->jobs = 1; + return NULL; + group->jobs = 1; group->exit_ok = group->exit_error = group->exit_total = group->force_exit = 0; if (pthread_mutex_init(&group->mutex, NULL)) { - logg("^Failed to initialize group mutex"); - free(group); - return NULL; + logg("^Failed to initialize group mutex"); + free(group); + return NULL; } if (pthread_cond_init(&group->only, NULL)) { - logg("^Failed to initialize group cond"); - pthread_mutex_destroy(&group->mutex); - free(group); - return NULL; + logg("^Failed to initialize group cond"); + pthread_mutex_destroy(&group->mutex); + free(group); + return NULL; } logg("$THRMGR: new group: %p\n", group); return group; @@ -876,11 +871,11 @@ { int ret; if (group) { - pthread_mutex_lock(&group->mutex); - ret = group->force_exit; - pthread_mutex_unlock(&group->mutex); + pthread_mutex_lock(&group->mutex); + ret = group->force_exit; + pthread_mutex_unlock(&group->mutex); } else - ret = 0; + ret = 0; pthread_mutex_lock(&exit_mutex); ret |= progexit; pthread_mutex_unlock(&exit_mutex); @@ -890,10 +885,10 @@ void thrmgr_group_terminate(jobgroup_t *group) { if (group) { - /* we may not be the last active job, now + /* we may not be the last active job, now * the last active job will free resources */ - pthread_mutex_lock(&group->mutex); - group->force_exit = 1; - pthread_mutex_unlock(&group->mutex); + pthread_mutex_lock(&group->mutex); + group->force_exit = 1; + pthread_mutex_unlock(&group->mutex); } } diff -Nru clamav-0.101.4+dfsg/clamd/thrmgr.h clamav-0.102.1+dfsg/clamd/thrmgr.h --- clamav-0.101.4+dfsg/clamd/thrmgr.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamd/thrmgr.h 2019-11-20 04:42:24.000000000 +0000 @@ -30,65 +30,65 @@ #endif typedef struct work_item_tag { - struct work_item_tag *next; - void *data; - struct timeval time_queued; + struct work_item_tag *next; + void *data; + struct timeval time_queued; } work_item_t; - + typedef struct work_queue_tag { - work_item_t *head; - work_item_t *tail; - int item_count; - int popped; + work_item_t *head; + work_item_t *tail; + int item_count; + int popped; } work_queue_t; typedef enum { - POOL_INVALID, - POOL_VALID, - POOL_EXIT + POOL_INVALID, + POOL_VALID, + POOL_EXIT } pool_state_t; struct task_desc { - const char *filename; - const char *command; - struct timeval tv; - struct task_desc *prv; - struct task_desc *nxt; - const struct cl_engine *engine; + const char *filename; + const char *command; + struct timeval tv; + struct task_desc *prv; + struct task_desc *nxt; + const struct cl_engine *engine; }; typedef struct threadpool_tag { - pthread_mutex_t pool_mutex; - pthread_cond_t pool_cond; - pthread_attr_t pool_attr; - - pthread_cond_t idle_cond; - pthread_cond_t queueable_single_cond; - pthread_cond_t queueable_bulk_cond; - - pool_state_t state; - int thr_max; - int queue_max; - int thr_alive; - int thr_idle; - int thr_multiscan; - int idle_timeout; - struct task_desc *tasks; - - void (*handler)(void *); + pthread_mutex_t pool_mutex; + pthread_cond_t pool_cond; + pthread_attr_t pool_attr; + + pthread_cond_t idle_cond; + pthread_cond_t queueable_single_cond; + pthread_cond_t queueable_bulk_cond; + + pool_state_t state; + int thr_max; + int queue_max; + int thr_alive; + int thr_idle; + int thr_multiscan; + int idle_timeout; + struct task_desc *tasks; + + void (*handler)(void *); - work_queue_t *bulk_queue; - work_queue_t *single_queue; + work_queue_t *bulk_queue; + work_queue_t *single_queue; } threadpool_t; typedef struct jobgroup { pthread_mutex_t mutex; pthread_cond_t only; - unsigned jobs; - unsigned exit_ok; - unsigned exit_error; - unsigned exit_total; - int force_exit; + unsigned jobs; + unsigned exit_ok; + unsigned exit_error; + unsigned exit_total; + int force_exit; } jobgroup_t; enum thrmgr_exit { @@ -107,7 +107,7 @@ void thrmgr_group_terminate(jobgroup_t *group); jobgroup_t *thrmgr_group_new(void); int thrmgr_printstats(int outfd, char term); -void thrmgr_setactivetask(const char *filename, const char* command); +void thrmgr_setactivetask(const char *filename, const char *command); void thrmgr_setactiveengine(const struct cl_engine *engine); #endif diff -Nru clamav-0.101.4+dfsg/clamdscan/Makefile.in clamav-0.102.1+dfsg/clamdscan/Makefile.in --- clamav-0.101.4+dfsg/clamdscan/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdscan/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -34,7 +34,17 @@ # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -100,8 +110,6 @@ target_triplet = @target@ @BUILD_CLAMD_TRUE@bin_PROGRAMS = clamdscan$(EXEEXT) subdir = clamdscan -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -114,6 +122,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -138,7 +147,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -156,7 +166,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -172,9 +181,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -182,6 +191,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -268,6 +278,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -301,12 +312,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -338,8 +354,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -369,7 +383,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -390,6 +408,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -402,6 +421,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -413,6 +435,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -444,6 +467,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -452,6 +477,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -464,6 +490,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -493,6 +520,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -508,6 +536,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ @BUILD_CLAMD_TRUE@clamdscan_SOURCES = \ @BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/output.c \ @BUILD_CLAMD_TRUE@ $(top_srcdir)/shared/output.h \ @@ -547,7 +576,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamdscan/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamdscan/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -969,6 +997,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamdscan/clamdscan.c clamav-0.102.1+dfsg/clamdscan/clamdscan.c --- clamav-0.101.4+dfsg/clamdscan/clamdscan.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdscan/clamdscan.c 2019-11-20 04:42:24.000000000 +0000 @@ -52,87 +52,85 @@ static void print_server_version(const struct optstruct *opt) { - if(get_clamd_version(opt)) { - /* can't get version from server, fallback */ - printf("ClamAV %s\n", get_version()); + if (get_clamd_version(opt)) { + /* can't get version from server, fallback */ + printf("ClamAV %s\n", get_version()); } } int main(int argc, char **argv) { - int ds, dms, ret, infected = 0, err = 0; - struct timeval t1, t2; - time_t starttime; - struct optstruct *opts; - const struct optstruct *opt; + int ds, dms, ret, infected = 0, err = 0; + struct timeval t1, t2; + time_t starttime; + struct optstruct *opts; + const struct optstruct *opt; #ifndef _WIN32 - struct sigaction sigact; + struct sigaction sigact; #endif - if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMDSCAN, OPT_CLAMSCAN, NULL)) == NULL) { - mprintf("!Can't parse command line options\n"); - return 2; + if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMDSCAN, OPT_CLAMSCAN, NULL)) == NULL) { + mprintf("!Can't parse command line options\n"); + return 2; } - if((clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { - logg("!Can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg); - return 2; + if (optget(opts, "help")->enabled) { + optfree(opts); + help(); } - if(optget(opts, "verbose")->enabled) { - mprintf_verbose = 1; - logg_verbose = 1; + if ((clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL)) == NULL) { + logg("!Can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg); + return 2; } - if(optget(opts, "quiet")->enabled) - mprintf_quiet = 1; + if (optget(opts, "verbose")->enabled) { + mprintf_verbose = 1; + logg_verbose = 1; + } - if(optget(opts, "stdout")->enabled) - mprintf_stdout = 1; + if (optget(opts, "quiet")->enabled) + mprintf_quiet = 1; - if(optget(opts, "version")->enabled) { - print_server_version(opts); - optfree(opts); - optfree(clamdopts); - exit(0); - } + if (optget(opts, "stdout")->enabled) + mprintf_stdout = 1; - if(optget(opts, "help")->enabled) { - optfree(opts); - optfree(clamdopts); - help(); + if (optget(opts, "version")->enabled) { + print_server_version(opts); + optfree(opts); + optfree(clamdopts); + exit(0); } - if(optget(opts, "infected")->enabled) - printinfected = 1; + if (optget(opts, "infected")->enabled) + printinfected = 1; /* initialize logger */ - if((opt = optget(opts, "log"))->enabled) { - logg_file = opt->strarg; - if(logg("--------------------------------------\n")) { - mprintf("!Problem with internal logger.\n"); - optfree(opts); - optfree(clamdopts); - exit(2); - } - } else - logg_file = NULL; - - - if(optget(opts, "reload")->enabled) { - ret = reload_clamd_database(opts); - optfree(opts); - optfree(clamdopts); - logg_close(); - exit(ret); - } - - if(actsetup(opts)) { - optfree(opts); - optfree(clamdopts); - logg_close(); - exit(2); + if ((opt = optget(opts, "log"))->enabled) { + logg_file = opt->strarg; + if (logg("--------------------------------------\n")) { + mprintf("!Problem with internal logger.\n"); + optfree(opts); + optfree(clamdopts); + exit(2); + } + } else + logg_file = NULL; + + if (optget(opts, "reload")->enabled) { + ret = reload_clamd_database(opts); + optfree(opts); + optfree(clamdopts); + logg_close(); + exit(ret); + } + + if (actsetup(opts)) { + optfree(opts); + optfree(clamdopts); + logg_close(); + exit(2); } #ifndef _WIN32 @@ -152,28 +150,28 @@ optfree(clamdopts); /* TODO: Implement STATUS in clamd */ - if(!optget(opts, "no-summary")->enabled) { - gettimeofday(&t2, NULL); - ds = t2.tv_sec - t1.tv_sec; - dms = t2.tv_usec - t1.tv_usec; - ds -= (dms < 0) ? (1):(0); - dms += (dms < 0) ? (1000000):(0); - logg("\n----------- SCAN SUMMARY -----------\n"); - logg("Infected files: %d\n", infected); - if(err) - logg("Total errors: %d\n", err); - if(notremoved) { - logg("Not removed: %d\n", notremoved); - } - if(notmoved) { - logg("Not moved: %d\n", notmoved); - } - logg("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms/1000, ds/60, ds%60); + if (!optget(opts, "no-summary")->enabled) { + gettimeofday(&t2, NULL); + ds = t2.tv_sec - t1.tv_sec; + dms = t2.tv_usec - t1.tv_usec; + ds -= (dms < 0) ? (1) : (0); + dms += (dms < 0) ? (1000000) : (0); + logg("\n----------- SCAN SUMMARY -----------\n"); + logg("Infected files: %d\n", infected); + if (err) + logg("Total errors: %d\n", err); + if (notremoved) { + logg("Not removed: %d\n", notremoved); + } + if (notmoved) { + logg("Not moved: %d\n", notmoved); + } + logg("Time: %d.%3.3d sec (%d m %d s)\n", ds, dms / 1000, ds / 60, ds % 60); } logg_close(); optfree(opts); - cl_cleanup_crypto(); + exit(ret); } @@ -192,7 +190,7 @@ mprintf(" --version -V Print version number and exit\n"); mprintf(" --verbose -v Be verbose\n"); mprintf(" --quiet Be quiet, only output error messages\n"); - mprintf(" --stdout Write to stdout instead of stderr\n"); + mprintf(" --stdout Write to stdout instead of stderr. Does not affect 'debug' messages.\n"); mprintf(" (this help is always written to stdout)\n"); mprintf(" --log=FILE -l FILE Save scan report in FILE\n"); mprintf(" --file-list=FILE -f FILE Scan files from FILE\n"); diff -Nru clamav-0.101.4+dfsg/clamdscan/client.c clamav-0.102.1+dfsg/clamdscan/client.c --- clamav-0.101.4+dfsg/clamdscan/client.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdscan/client.c 2019-11-20 04:42:24.000000000 +0000 @@ -25,7 +25,7 @@ #include #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #include @@ -74,7 +74,8 @@ /* Inits the communication layer * Returns 0 if clamd is local, non zero if clamd is remote */ -static int isremote(const struct optstruct *opts) { +static int isremote(const struct optstruct *opts) +{ int s, ret; const struct optstruct *opt; char *ipaddr, port[10]; @@ -84,15 +85,15 @@ UNUSEDPARAM(opts); #ifndef _WIN32 - if((opt = optget(clamdopts, "LocalSocket"))->enabled) { + if ((opt = optget(clamdopts, "LocalSocket"))->enabled) { memset((void *)&nixsock, 0, sizeof(nixsock)); nixsock.sun_family = AF_UNIX; strncpy(nixsock.sun_path, opt->strarg, sizeof(nixsock.sun_path)); - nixsock.sun_path[sizeof(nixsock.sun_path)-1]='\0'; + nixsock.sun_path[sizeof(nixsock.sun_path) - 1] = '\0'; return 0; } #endif - if(!(opt = optget(clamdopts, "TCPSocket"))->enabled) + if (!(opt = optget(clamdopts, "TCPSocket"))->enabled) return 0; snprintf(port, sizeof(port), "%lld", optget(clamdopts, "TCPSocket")->numarg); @@ -104,9 +105,9 @@ ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; if ((res = getaddrinfo(ipaddr, port, &hints, &info))) { logg("!Can't lookup clamd hostname: %s\n", gai_strerror(res)); @@ -115,20 +116,20 @@ } for (p = info; p != NULL; p = p->ai_next) { - if((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { + if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { logg("isremote: socket() returning: %s.\n", strerror(errno)); continue; } switch (p->ai_family) { - case AF_INET: - ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY); - break; - case AF_INET6: - ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY); - break; - default: - break; + case AF_INET: + ((struct sockaddr_in *)(p->ai_addr))->sin_port = htons(INADDR_ANY); + break; + case AF_INET6: + ((struct sockaddr_in6 *)(p->ai_addr))->sin6_port = htons(INADDR_ANY); + break; + default: + break; } ret = bind(s, p->ai_addr, p->ai_addrlen); @@ -159,34 +160,34 @@ return 0; } - /* Turns a relative path into an absolute one * Returns a pointer to the path (which must be * freed by the caller) or NULL on error */ -static char *makeabs(const char *basepath) { +static char *makeabs(const char *basepath) +{ int namelen; char *ret; - if(!(ret = malloc(PATH_MAX + 1))) { - logg("^Can't make room for fullpath.\n"); - return NULL; + if (!(ret = malloc(PATH_MAX + 1))) { + logg("^Can't make room for fullpath.\n"); + return NULL; } - if(!cli_is_abspath(basepath)) { - if(!getcwd(ret, PATH_MAX)) { - logg("^Can't get absolute pathname of current working directory.\n"); - free(ret); - return NULL; - } + if (!cli_is_abspath(basepath)) { + if (!getcwd(ret, PATH_MAX)) { + logg("^Can't get absolute pathname of current working directory.\n"); + free(ret); + return NULL; + } #ifdef _WIN32 - if(*basepath == '\\') { - namelen = 2; - basepath++; - } else + if (*basepath == '\\') { + namelen = 2; + basepath++; + } else #endif - namelen = strlen(ret); - snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP"%s", basepath); + namelen = strlen(ret); + snprintf(&ret[namelen], PATH_MAX - namelen, PATHSEP "%s", basepath); } else { - strncpy(ret, basepath, PATH_MAX); + strncpy(ret, basepath, PATH_MAX); } ret[PATH_MAX] = '\0'; return ret; @@ -194,41 +195,42 @@ /* Recursively scans a path with the given scantype * Returns non zero for serious errors, zero otherwise */ -static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) { +static int client_scan(const char *file, int scantype, int *infected, int *err, int maxlevel, int session, int flags) +{ int ret; char *fullpath = makeabs(file); - if(!fullpath) - return 0; + if (!fullpath) + return 0; if (!session) - ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags); + ret = serial_client_scan(fullpath, scantype, infected, err, maxlevel, flags); else - ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags); + ret = parallel_client_scan(fullpath, scantype, infected, err, maxlevel, flags); free(fullpath); return ret; } int get_clamd_version(const struct optstruct *opts) { - char *buff; - int len, sockd; - struct RCVLN rcv; + char *buff; + int len, sockd; + struct RCVLN rcv; isremote(opts); - if((sockd = dconnect()) < 0) return 2; + if ((sockd = dconnect()) < 0) return 2; recvlninit(&rcv, sockd); - if(sendln(sockd, "zVERSION", 9)) { - closesocket(sockd); - return 2; + if (sendln(sockd, "zVERSION", 9)) { + closesocket(sockd); + return 2; } - while((len = recvln(&rcv, &buff, NULL))) { - if(len == -1) { - logg("!Error occurred while receiving version information.\n"); - break; - } - printf("%s\n", buff); + while ((len = recvln(&rcv, &buff, NULL))) { + if (len == -1) { + logg("!Error occurred while receiving version information.\n"); + break; + } + printf("%s\n", buff); } closesocket(sockd); @@ -237,23 +239,23 @@ int reload_clamd_database(const struct optstruct *opts) { - char *buff; - int len, sockd; - struct RCVLN rcv; + char *buff; + int len, sockd; + struct RCVLN rcv; isremote(opts); - if((sockd = dconnect()) < 0) return 2; + if ((sockd = dconnect()) < 0) return 2; recvlninit(&rcv, sockd); - if(sendln(sockd, "zRELOAD", 8)) { - closesocket(sockd); - return 2; + if (sendln(sockd, "zRELOAD", 8)) { + closesocket(sockd); + return 2; } - if(!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) { - logg("!Clamd did not reload the database\n"); - closesocket(sockd); - return 2; + if (!(len = recvln(&rcv, &buff, NULL)) || len < 10 || memcmp(buff, "RELOADING", 9)) { + logg("!Clamd did not reload the database\n"); + closesocket(sockd); + return 2; } closesocket(sockd); return 0; @@ -261,68 +263,70 @@ int client(const struct optstruct *opts, int *infected, int *err) { - int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0; - const char *fname; + int remote, scantype, session = 0, errors = 0, scandash = 0, maxrec, flags = 0; + const char *fname; scandash = (opts->filename && opts->filename[0] && !strcmp(opts->filename[0], "-") && !optget(opts, "file-list")->enabled && !opts->filename[1]); - remote = isremote(opts) | optget(opts, "stream")->enabled; + remote = isremote(opts) | optget(opts, "stream")->enabled; #ifdef HAVE_FD_PASSING - if(!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) { - scantype = FILDES; - session = optget(opts, "multiscan")->enabled; - } else + if (!remote && optget(clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled || scandash)) { + scantype = FILDES; + session = optget(opts, "multiscan")->enabled; + } else #endif - if(remote || scandash) { - scantype = STREAM; - session = optget(opts, "multiscan")->enabled; - } - else if(optget(opts, "multiscan")->enabled) scantype = MULTI; - else if(optget(opts, "allmatch")->enabled) scantype = ALLMATCH; - else scantype = CONT; + if (remote || scandash) { + scantype = STREAM; + session = optget(opts, "multiscan")->enabled; + } else if (optget(opts, "multiscan")->enabled) + scantype = MULTI; + else if (optget(opts, "allmatch")->enabled) + scantype = ALLMATCH; + else + scantype = CONT; - maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg; + maxrec = optget(clamdopts, "MaxDirectoryRecursion")->numarg; maxstream = optget(clamdopts, "StreamMaxLength")->numarg; if (optget(clamdopts, "FollowDirectorySymlinks")->enabled) - flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; + flags |= CLI_FTW_FOLLOW_DIR_SYMLINK; if (optget(clamdopts, "FollowFileSymlinks")->enabled) - flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; + flags |= CLI_FTW_FOLLOW_FILE_SYMLINK; flags |= CLI_FTW_TRIM_SLASHES; *infected = 0; - if(scandash) { - int sockd, ret; - STATBUF sb; - if(FSTAT(0, &sb) < 0) { - logg("client.c: fstat failed for file name \"%s\", with %s\n.", - opts->filename[0], strerror(errno)); - return 2; - } - if((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM; - if((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0) - *infected = ret; - else - errors = 1; - if(sockd >= 0) closesocket(sockd); - } else if(opts->filename || optget(opts, "file-list")->enabled) { - if(opts->filename && optget(opts, "file-list")->enabled) - logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n"); - - while((fname = filelist(opts, NULL))) { - if(!strcmp(fname, "-")) { - logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); - continue; - } - errors += client_scan(fname, scantype, infected, err, maxrec, session, flags); - /* this may be too strict + if (scandash) { + int sockd, ret; + STATBUF sb; + if (FSTAT(0, &sb) < 0) { + logg("client.c: fstat failed for file name \"%s\", with %s\n.", + opts->filename[0], strerror(errno)); + return 2; + } + if ((sb.st_mode & S_IFMT) != S_IFREG) scantype = STREAM; + if ((sockd = dconnect()) >= 0 && (ret = dsresult(sockd, scantype, NULL, &ret, NULL)) >= 0) + *infected = ret; + else + errors = 1; + if (sockd >= 0) closesocket(sockd); + } else if (opts->filename || optget(opts, "file-list")->enabled) { + if (opts->filename && optget(opts, "file-list")->enabled) + logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n"); + + while ((fname = filelist(opts, NULL))) { + if (!strcmp(fname, "-")) { + logg("!Scanning from standard input requires \"-\" to be the only file argument\n"); + continue; + } + errors += client_scan(fname, scantype, infected, err, maxrec, session, flags); + /* this may be too strict if(errors >= 10) { logg("!Too many errors\n"); break; } */ - } + } } else { - errors = client_scan("", scantype, infected, err, maxrec, session, flags); + errors = client_scan("", scantype, infected, err, maxrec, session, flags); } return *infected ? 1 : (errors ? 2 : 0); } diff -Nru clamav-0.101.4+dfsg/clamdscan/proto.c clamav-0.102.1+dfsg/clamdscan/proto.c --- clamav-0.101.4+dfsg/clamdscan/proto.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdscan/proto.c 2019-11-20 04:42:24.000000000 +0000 @@ -69,11 +69,12 @@ extern struct sockaddr_un nixsock; #endif -static const char *scancmd[] = { "CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN" }; +static const char *scancmd[] = {"CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN"}; /* Connects to clamd * Returns a FD or -1 on error */ -int dconnect() { +int dconnect() +{ int sockd, res; const struct optstruct *opt; struct addrinfo hints, *info, *p; @@ -104,7 +105,7 @@ ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((res = getaddrinfo(ipaddr, port, &hints, &info))) { @@ -114,12 +115,12 @@ } for (p = info; p != NULL; p = p->ai_next) { - if((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { + if ((sockd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) { logg("!Can't create the socket: %s\n", strerror(errno)); continue; } - if(connect(sockd, p->ai_addr, p->ai_addrlen) < 0) { + if (connect(sockd, p->ai_addr, p->ai_addrlen) < 0) { logg("!Could not connect to clamd on %s: %s\n", opt->strarg, strerror(errno)); closesocket(sockd); continue; @@ -139,42 +140,44 @@ /* Issues an INSTREAM command to clamd and streams the given file * Returns >0 on success, 0 soft fail, -1 hard fail */ -static int send_stream(int sockd, const char *filename) { - uint32_t buf[BUFSIZ/sizeof(uint32_t)]; +static int send_stream(int sockd, const char *filename) +{ + uint32_t buf[BUFSIZ / sizeof(uint32_t)]; int fd, len; unsigned long int todo = maxstream; - if(filename) { - if((fd = safe_open(filename, O_RDONLY | O_BINARY))<0) { - logg("~%s: Access denied. ERROR\n", filename); - return 0; - } - } else fd = 0; - - if(sendln(sockd, "zINSTREAM", 10)) { - close(fd); - return -1; - } - - while((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { - if((unsigned int)len > todo) len = todo; - buf[0] = htonl(len); - if(sendln(sockd, (const char *)buf, len+sizeof(uint32_t))) { - close(fd); - return -1; - } - todo -= len; - if(!todo) { - len = 0; - break; - } + if (filename) { + if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) { + logg("~%s: Access denied. ERROR\n", filename); + return 0; + } + } else + fd = 0; + + if (sendln(sockd, "zINSTREAM", 10)) { + close(fd); + return -1; + } + + while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { + if ((unsigned int)len > todo) len = todo; + buf[0] = htonl(len); + if (sendln(sockd, (const char *)buf, len + sizeof(uint32_t))) { + close(fd); + return -1; + } + todo -= len; + if (!todo) { + len = 0; + break; + } } close(fd); - if(len) { - logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); - return 0; + if (len) { + logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); + return 0; } - *buf=0; + *buf = 0; sendln(sockd, (const char *)buf, 4); return 1; } @@ -182,41 +185,43 @@ #ifdef HAVE_FD_PASSING /* Issues a FILDES command and pass a FD to clamd * Returns >0 on success, 0 soft fail, -1 hard fail */ -static int send_fdpass(int sockd, const char *filename) { +static int send_fdpass(int sockd, const char *filename) +{ struct iovec iov[1]; struct msghdr msg; struct cmsghdr *cmsg; unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; - char dummy[]=""; + char dummy[] = ""; int fd; - if(filename) { - if((fd = open(filename, O_RDONLY))<0) { - logg("~%s: Access denied. ERROR\n", filename); - return 0; - } - } else fd = 0; - if(sendln(sockd, "zFILDES", 8)) { - close(fd); - return -1; + if (filename) { + if ((fd = open(filename, O_RDONLY)) < 0) { + logg("~%s: Access denied. ERROR\n", filename); + return 0; + } + } else + fd = 0; + if (sendln(sockd, "zFILDES", 8)) { + close(fd); + return -1; } iov[0].iov_base = dummy; - iov[0].iov_len = 1; + iov[0].iov_len = 1; memset(&msg, 0, sizeof(msg)); - msg.msg_control = fdbuf; - msg.msg_iov = iov; - msg.msg_iovlen = 1; - msg.msg_controllen = CMSG_LEN(sizeof(int)); - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; + msg.msg_control = fdbuf; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; *(int *)CMSG_DATA(cmsg) = fd; - if(sendmsg(sockd, &msg, 0) == -1) { - logg("!FD send failed: %s\n", strerror(errno)); - close(fd); - return -1; + if (sendmsg(sockd, &msg, 0) == -1) { + logg("!FD send failed: %s\n", strerror(errno)); + close(fd); + return -1; } close(fd); return 1; @@ -226,17 +231,17 @@ /* 0: scan, 1: skip */ static int chkpath(const char *path) { - const struct optstruct *opt; + const struct optstruct *opt; - if((opt = optget(clamdopts, "ExcludePath"))->enabled) { - while(opt) { - if(match_regex(path, opt->strarg) == 1) { + if ((opt = optget(clamdopts, "ExcludePath"))->enabled) { + while (opt) { + if (match_regex(path, opt->strarg) == 1) { if (printinfected != 1) logg("~%s: Excluded\n", path); - return 1; - } - opt = opt->nextarg; - } + return 1; + } + opt = opt->nextarg; + } } return 0; } @@ -251,83 +256,83 @@ * This is used only in non IDSESSION mode * Returns the number of infected files or -1 on error * NOTE: filename may be NULL for STREAM scantype. */ -int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) { +int dsresult(int sockd, int scantype, const char *filename, int *printok, int *errors) +{ int infected = 0, len = 0, beenthere = 0; char *bol, *eol; struct RCVLN rcv; STATBUF sb; - if(filename && chkpath(filename)) - return 0; + if (filename && chkpath(filename)) + return 0; recvlninit(&rcv, sockd); - switch(scantype) { - case MULTI: - case CONT: - case ALLMATCH: - if (!filename) { - logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); - return -1; - } - len = strlen(filename) + strlen(scancmd[scantype]) + 3; - if (!(bol = malloc(len))) { - logg("!Cannot allocate a command buffer: %s\n", strerror(errno)); - return -1; - } - sprintf(bol, "z%s %s", scancmd[scantype], filename); - if(sendln(sockd, bol, len)) { - free(bol); - return -1; - } - free(bol); - break; - - case STREAM: - /* NULL filename safe in send_stream() */ - len = send_stream(sockd, filename); - break; + switch (scantype) { + case MULTI: + case CONT: + case ALLMATCH: + if (!filename) { + logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); + return -1; + } + len = strlen(filename) + strlen(scancmd[scantype]) + 3; + if (!(bol = malloc(len))) { + logg("!Cannot allocate a command buffer: %s\n", strerror(errno)); + return -1; + } + sprintf(bol, "z%s %s", scancmd[scantype], filename); + if (sendln(sockd, bol, len)) { + free(bol); + return -1; + } + free(bol); + break; + + case STREAM: + /* NULL filename safe in send_stream() */ + len = send_stream(sockd, filename); + break; #ifdef HAVE_FD_PASSING - case FILDES: - /* NULL filename safe in send_fdpass() */ - len = send_fdpass(sockd, filename); - break; + case FILDES: + /* NULL filename safe in send_fdpass() */ + len = send_fdpass(sockd, filename); + break; #endif } - if(len <=0) { - *printok = 0; - if(errors) - (*errors)++; - return len; - } - - while((len = recvln(&rcv, &bol, &eol))) { - if(len == -1) return -1; - beenthere = 1; - if(!filename) logg("~%s\n", bol); - if(len > 7) { - char *colon = strrchr(bol, ':'); - if(colon && colon[1] != ' ') { - char *br; - *colon = 0; - br = strrchr(bol, '('); - if(br) - *br = 0; - colon = strrchr(bol, ':'); - } - if(!colon) { - char * unkco = "UNKNOWN COMMAND"; - if (!strncmp(bol, unkco, sizeof(unkco) - 1)) - logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", - (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : - scancmd[scantype]); - else - logg("Failed to parse reply: \"%s\"\n", bol); - return -1; - } else if(!memcmp(eol - 7, " FOUND", 6)) { - static char last_filename[PATH_MAX+1] = {'\0'}; - *(eol - 7) = 0; - *printok = 0; + if (len <= 0) { + *printok = 0; + if (errors) + (*errors)++; + return len; + } + + while ((len = recvln(&rcv, &bol, &eol))) { + if (len == -1) return -1; + beenthere = 1; + if (!filename) logg("~%s\n", bol); + if (len > 7) { + char *colon = strrchr(bol, ':'); + if (colon && colon[1] != ' ') { + char *br; + *colon = 0; + br = strrchr(bol, '('); + if (br) + *br = 0; + colon = strrchr(bol, ':'); + } + if (!colon) { + char *unkco = "UNKNOWN COMMAND"; + if (!strncmp(bol, unkco, sizeof(unkco) - 1)) + logg("clamd replied \"UNKNOWN COMMAND\". Command was %s\n", + (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : scancmd[scantype]); + else + logg("Failed to parse reply: \"%s\"\n", bol); + return -1; + } else if (!memcmp(eol - 7, " FOUND", 6)) { + static char last_filename[PATH_MAX + 1] = {'\0'}; + *(eol - 7) = 0; + *printok = 0; if (scantype != ALLMATCH) { infected++; } else { @@ -337,44 +342,44 @@ last_filename[PATH_MAX] = '\0'; } } - if(filename) { - if(scantype >= STREAM) { - logg("~%s%s FOUND\n", filename, colon); - if(action) action(filename); - } else { - logg("~%s FOUND\n", bol); - *colon = '\0'; - if(action) - action(bol); - } - } - } else if(!memcmp(eol-7, " ERROR", 6)) { - if(errors) - (*errors)++; - *printok = 0; - if(filename) { - if(scantype >= STREAM) - logg("~%s%s\n", filename, colon); - else - logg("~%s\n", bol); - } - } - } + if (filename) { + if (scantype >= STREAM) { + logg("~%s%s FOUND\n", filename, colon); + if (action) action(filename); + } else { + logg("~%s FOUND\n", bol); + *colon = '\0'; + if (action) + action(bol); + } + } + } else if (!memcmp(eol - 7, " ERROR", 6)) { + if (errors) + (*errors)++; + *printok = 0; + if (filename) { + if (scantype >= STREAM) + logg("~%s%s\n", filename, colon); + else + logg("~%s\n", bol); + } + } + } } - if(!beenthere) { + if (!beenthere) { if (!filename) { - logg("STDIN: noreply from clamd\n."); - return -1; - } - if(CLAMSTAT(filename, &sb) == -1) { - logg("~%s: stat() failed with %s, clamd may not be responding\n", - filename, strerror(errno)); - return -1; - } - if(!S_ISDIR(sb.st_mode)) { - logg("~%s: no reply from clamd\n", filename); - return -1; - } + logg("STDIN: noreply from clamd\n."); + return -1; + } + if (CLAMSTAT(filename, &sb) == -1) { + logg("~%s: stat() failed with %s, clamd may not be responding\n", + filename, strerror(errno)); + return -1; + } + if (!S_ISDIR(sb.st_mode)) { + logg("~%s: no reply from clamd\n", filename); + return -1; + } } return infected; } @@ -390,85 +395,87 @@ /* FTW callback for scanning in non IDSESSION mode * Returns SUCCESS or BREAK on success, CL_EXXX on error */ -static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { +static int serial_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) +{ struct client_serial_data *c = (struct client_serial_data *)data->data; int sockd, ret; const char *f = filename; UNUSEDPARAM(sb); - if(chkpath(path)) - return CL_SUCCESS; + if (chkpath(path)) + return CL_SUCCESS; c->files++; - switch(reason) { - case error_stat: - logg("!Can't access file %s\n", path); - c->errors++; - return CL_SUCCESS; - case error_mem: - logg("!Memory allocation failed in ftw\n"); - c->errors++; - return CL_EMEM; - case warning_skipped_dir: - logg("^Directory recursion limit reached\n"); - case warning_skipped_link: - return CL_SUCCESS; - case warning_skipped_special: - logg("^%s: Not supported file type\n", path); - c->errors++; - return CL_SUCCESS; - case visit_directory_toplev: - if(c->scantype >= STREAM) - return CL_SUCCESS; - f = path; - filename = NULL; - case visit_file: - break; - } - - if((sockd = dconnect()) < 0) { - if(filename) free(filename); - c->errors++; - return CL_EOPEN; + switch (reason) { + case error_stat: + logg("!Can't access file %s\n", path); + c->errors++; + return CL_SUCCESS; + case error_mem: + logg("!Memory allocation failed in ftw\n"); + c->errors++; + return CL_EMEM; + case warning_skipped_dir: + logg("^Directory recursion limit reached\n"); + case warning_skipped_link: + return CL_SUCCESS; + case warning_skipped_special: + logg("^%s: Not supported file type\n", path); + c->errors++; + return CL_SUCCESS; + case visit_directory_toplev: + if (c->scantype >= STREAM) + return CL_SUCCESS; + f = path; + filename = NULL; + case visit_file: + break; + } + + if ((sockd = dconnect()) < 0) { + if (filename) free(filename); + c->errors++; + return CL_EOPEN; } ret = dsresult(sockd, c->scantype, f, &c->printok, &c->errors); - if(filename) free(filename); + if (filename) free(filename); closesocket(sockd); - if(ret < 0) { - c->errors++; - return CL_EOPEN; + if (ret < 0) { + c->errors++; + return CL_EOPEN; } c->infected += ret; - if(reason == visit_directory_toplev) - return CL_BREAK; + if (reason == visit_directory_toplev) + return CL_BREAK; return CL_SUCCESS; } /* Non-IDSESSION handler * Returns non zero for serious errors, zero otherwise */ -int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) { +int serial_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) +{ struct cli_ftw_cbdata data; struct client_serial_data cdata; int ftw; cdata.infected = 0; - cdata.files = 0; - cdata.errors = 0; - cdata.printok = printinfected^1; + cdata.files = 0; + cdata.errors = 0; + cdata.printok = printinfected ^ 1; cdata.scantype = scantype; - data.data = &cdata; + data.data = &cdata; ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, serial_callback, &data, ftw_chkpath); *infected += cdata.infected; *err += cdata.errors; - if(!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) { - if(cdata.printok) - logg("~%s: OK\n", file); - return 0; - } else if(!cdata.files) { - logg("~%s: No files scanned\n", file); - return 0; + if (!cdata.errors && (ftw == CL_SUCCESS || ftw == CL_BREAK)) { + if (cdata.printok) + logg("~%s: OK\n", file); + return 0; + } else if (!cdata.files) { + logg("~%s: No files scanned\n", file); + return 0; } return 1; } @@ -483,16 +490,17 @@ int lastid; int printok; struct SCANID { - unsigned int id; - const char *file; - struct SCANID *next; - } *ids; + unsigned int id; + const char *file; + struct SCANID *next; + } * ids; }; /* Sends a proper scan request to clamd and parses its replies * This is used only in IDSESSION mode * Returns 0 on success, 1 on hard failures, 2 on len == 0 (bb#1717) */ -static int dspresult(struct client_parallel_data *c) { +static int dspresult(struct client_parallel_data *c) +{ const char *filename; char *bol, *eol; unsigned int rid; @@ -502,190 +510,193 @@ recvlninit(&rcv, c->sockd); do { - len = recvln(&rcv, &bol, &eol); - if(len < 0) return 1; - if(!len) return 2; - if((rid = atoi(bol))) { - id = &c->ids; - while(*id) { - if((*id)->id == rid) break; - id = &((*id)->next); - } - if(!*id) id = NULL; - } - if(!id) { - logg("!Bogus session id from clamd\n"); - return 1; - } - filename = (*id)->file; - if(len > 7) { - char *colon = strrchr(bol, ':'); - if(!colon) { - logg("!Failed to parse reply\n"); - free((void *)filename); - return 1; - } else if(!memcmp(eol - 7, " FOUND", 6)) { - c->infected++; - c->printok = 0; - logg("~%s%s\n", filename, colon); - if(action) action(filename); - } else if(!memcmp(eol-7, " ERROR", 6)) { - c->errors++; - c->printok = 0; - logg("~%s%s\n", filename, colon); - } - } - free((void *)filename); - bol = (char *)*id; - *id = (*id)->next; - free(bol); - } while(rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume + len = recvln(&rcv, &bol, &eol); + if (len < 0) return 1; + if (!len) return 2; + if ((rid = atoi(bol))) { + id = &c->ids; + while (*id) { + if ((*id)->id == rid) break; + id = &((*id)->next); + } + if (!*id) id = NULL; + } + if (!id) { + logg("!Bogus session id from clamd\n"); + return 1; + } + filename = (*id)->file; + if (len > 7) { + char *colon = strrchr(bol, ':'); + if (!colon) { + logg("!Failed to parse reply\n"); + free((void *)filename); + return 1; + } else if (!memcmp(eol - 7, " FOUND", 6)) { + c->infected++; + c->printok = 0; + logg("~%s%s\n", filename, colon); + if (action) action(filename); + } else if (!memcmp(eol - 7, " ERROR", 6)) { + c->errors++; + c->printok = 0; + logg("~%s%s\n", filename, colon); + } + } + free((void *)filename); + bol = (char *)*id; + *id = (*id)->next; + free(bol); + } while (rcv.cur != rcv.buf); /* clamd sends whole lines, so, on partial lines, we just assume more data can be recv()'d with close to zero latency */ return 0; } /* FTW callback for scanning in IDSESSION mode * Returns SUCCESS on success, CL_EXXX or BREAK on error */ -static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) { +static int parallel_callback(STATBUF *sb, char *filename, const char *path, enum cli_ftw_reason reason, struct cli_ftw_cbdata *data) +{ struct client_parallel_data *c = (struct client_parallel_data *)data->data; struct SCANID *cid; int res = CL_CLEAN; UNUSEDPARAM(sb); - if(chkpath(path)) - return CL_SUCCESS; + if (chkpath(path)) + return CL_SUCCESS; c->files++; - switch(reason) { - case error_stat: - logg("!Can't access file %s\n", path); - c->errors++; - return CL_SUCCESS; - case error_mem: - logg("!Memory allocation failed in ftw\n"); - c->errors++; - return CL_EMEM; - case warning_skipped_dir: - logg("^Directory recursion limit reached\n"); - return CL_SUCCESS; - case warning_skipped_special: - logg("^%s: Not supported file type\n", path); - c->errors++; - case warning_skipped_link: - case visit_directory_toplev: - return CL_SUCCESS; - case visit_file: - break; + switch (reason) { + case error_stat: + logg("!Can't access file %s\n", path); + c->errors++; + return CL_SUCCESS; + case error_mem: + logg("!Memory allocation failed in ftw\n"); + c->errors++; + return CL_EMEM; + case warning_skipped_dir: + logg("^Directory recursion limit reached\n"); + return CL_SUCCESS; + case warning_skipped_special: + logg("^%s: Not supported file type\n", path); + c->errors++; + case warning_skipped_link: + case visit_directory_toplev: + return CL_SUCCESS; + case visit_file: + break; } - while(1) { - /* consume all the available input to let some of the clamd + while (1) { + /* consume all the available input to let some of the clamd * threads blocked on send() to be dead. * by doing so we shouldn't deadlock on the next recv() */ - fd_set rfds, wfds; - FD_ZERO(&rfds); - FD_SET(c->sockd, &rfds); - FD_ZERO(&wfds); - FD_SET(c->sockd, &wfds); - if(select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) { - if(errno == EINTR) continue; - free(filename); - logg("!select() failed during session: %s\n", strerror(errno)); - return CL_BREAK; - } - if(FD_ISSET(c->sockd, &rfds)) { - if(dspresult(c)) { - free(filename); - return CL_BREAK; - } else continue; - } - if(FD_ISSET(c->sockd, &wfds)) break; + fd_set rfds, wfds; + FD_ZERO(&rfds); + FD_SET(c->sockd, &rfds); + FD_ZERO(&wfds); + FD_SET(c->sockd, &wfds); + if (select(c->sockd + 1, &rfds, &wfds, NULL, NULL) < 0) { + if (errno == EINTR) continue; + free(filename); + logg("!select() failed during session: %s\n", strerror(errno)); + return CL_BREAK; + } + if (FD_ISSET(c->sockd, &rfds)) { + if (dspresult(c)) { + free(filename); + return CL_BREAK; + } else + continue; + } + if (FD_ISSET(c->sockd, &wfds)) break; } cid = (struct SCANID *)malloc(sizeof(struct SCANID)); - if(!cid) { - free(filename); - logg("!Failed to allocate scanid entry: %s\n", strerror(errno)); - return CL_BREAK; + if (!cid) { + free(filename); + logg("!Failed to allocate scanid entry: %s\n", strerror(errno)); + return CL_BREAK; } - cid->id = ++c->lastid; + cid->id = ++c->lastid; cid->file = filename; cid->next = c->ids; - c->ids = cid; + c->ids = cid; - switch(c->scantype) { + switch (c->scantype) { #ifdef HAVE_FD_PASSING - case FILDES: - res = send_fdpass(c->sockd, filename); - break; + case FILDES: + res = send_fdpass(c->sockd, filename); + break; #endif - case STREAM: - res = send_stream(c->sockd, filename); - break; - } - if(res <= 0) { - c->printok = 0; - c->errors++; - c->ids = cid->next; - c->lastid--; - free(cid); - free(filename); - return res ? CL_BREAK : CL_SUCCESS; + case STREAM: + res = send_stream(c->sockd, filename); + break; + } + if (res <= 0) { + c->printok = 0; + c->errors++; + c->ids = cid->next; + c->lastid--; + free(cid); + free(filename); + return res ? CL_BREAK : CL_SUCCESS; } return CL_SUCCESS; } /* IDSESSION handler * Returns non zero for serious errors, zero otherwise */ -int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) { +int parallel_client_scan(char *file, int scantype, int *infected, int *err, int maxlevel, int flags) +{ struct cli_ftw_cbdata data; struct client_parallel_data cdata; int ftw; - if((cdata.sockd = dconnect()) < 0) - return 1; + if ((cdata.sockd = dconnect()) < 0) + return 1; - if(sendln(cdata.sockd, "zIDSESSION", 11)) { - closesocket(cdata.sockd); - return 1; + if (sendln(cdata.sockd, "zIDSESSION", 11)) { + closesocket(cdata.sockd); + return 1; } cdata.infected = 0; - cdata.files = 0; - cdata.errors = 0; + cdata.files = 0; + cdata.errors = 0; cdata.scantype = scantype; - cdata.lastid = 0; - cdata.ids = NULL; - cdata.printok = printinfected^1; - data.data = &cdata; + cdata.lastid = 0; + cdata.ids = NULL; + cdata.printok = printinfected ^ 1; + data.data = &cdata; ftw = cli_ftw(file, flags, maxlevel ? maxlevel : INT_MAX, parallel_callback, &data, ftw_chkpath); - if(ftw != CL_SUCCESS) { - *err += cdata.errors; - *infected += cdata.infected; - closesocket(cdata.sockd); - return 1; + if (ftw != CL_SUCCESS) { + *err += cdata.errors; + *infected += cdata.infected; + closesocket(cdata.sockd); + return 1; } sendln(cdata.sockd, "zEND", 5); - while(cdata.ids && !dspresult(&cdata)); + while (cdata.ids && !dspresult(&cdata)) continue; closesocket(cdata.sockd); *infected += cdata.infected; *err += cdata.errors; - if(cdata.ids) { - logg("!Clamd closed the connection before scanning all files.\n"); - return 1; + if (cdata.ids) { + logg("!Clamd closed the connection before scanning all files.\n"); + return 1; } - if(cdata.errors) - return 1; + if (cdata.errors) + return 1; - if(!cdata.files) - return 0; + if (!cdata.files) + return 0; - if(cdata.printok) - logg("~%s: OK\n", file); + if (cdata.printok) + logg("~%s: OK\n", file); return 0; } diff -Nru clamav-0.101.4+dfsg/clamdtop/Makefile.in clamav-0.102.1+dfsg/clamdtop/Makefile.in --- clamav-0.101.4+dfsg/clamdtop/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdtop/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -15,7 +15,17 @@ @SET_MAKE@ VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -81,8 +91,6 @@ target_triplet = @target@ @HAVE_CURSES_TRUE@bin_PROGRAMS = clamdtop$(EXEEXT) subdir = clamdtop -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -95,6 +103,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -119,7 +128,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -137,7 +147,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -153,9 +162,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -163,6 +172,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -273,6 +283,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -306,12 +317,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -343,8 +359,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -374,7 +388,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -395,6 +413,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -407,6 +426,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -418,6 +440,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -449,6 +472,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -457,6 +482,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -469,6 +495,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -498,6 +525,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -513,6 +541,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ @HAVE_CURSES_TRUE@man_MANS = $(top_builddir)/docs/man/clamdtop.1 @HAVE_CURSES_TRUE@clamdtop_SOURCES = \ @HAVE_CURSES_TRUE@ $(top_srcdir)/shared/optparser.c \ @@ -543,7 +572,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamdtop/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamdtop/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -963,6 +991,8 @@ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-man uninstall-man1 +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamdtop/clamdtop.c clamav-0.102.1+dfsg/clamdtop/clamdtop.c --- clamav-0.101.4+dfsg/clamdtop/clamdtop.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamdtop/clamdtop.c 2019-11-20 04:42:24.000000000 +0000 @@ -64,39 +64,39 @@ /* Types, prototypes and globals*/ typedef struct connection { - int sd; - char *remote; - int tcp; - struct timeval tv_conn; - char *version; - int line; + int sd; + char *remote; + int tcp; + struct timeval tv_conn; + char *version; + int line; } conn_t; struct global_stats { - struct task *tasks; - ssize_t n; - struct stats *all_stats; - size_t num_clamd; - conn_t *conn; + struct task *tasks; + ssize_t n; + struct stats *all_stats; + size_t num_clamd; + conn_t *conn; }; struct stats { - const char *remote; - char *engine_version; - char *db_version; - struct tm db_time; - const char *version; - int stats_unsupp; - uint8_t conn_hr, conn_min, conn_sec; - /* threads - primary */ - unsigned prim_live, prim_idle, prim_max; - /* threads - sum */ - unsigned live, idle, max; - /* queue */ - unsigned biggest_queue, current_q; - double mem;/* in megabytes */ - unsigned long lheapu, lmmapu, ltotalu, ltotalf, lreleasable, lpoolu, lpoolt; - unsigned pools_cnt; + const char *remote; + char *engine_version; + char *db_version; + struct tm db_time; + const char *version; + int stats_unsupp; + uint8_t conn_hr, conn_min, conn_sec; + /* threads - primary */ + unsigned prim_live, prim_idle, prim_max; + /* threads - sum */ + unsigned live, idle, max; + /* queue */ + unsigned biggest_queue, current_q; + double mem; /* in megabytes */ + unsigned long lheapu, lmmapu, ltotalu, ltotalf, lreleasable, lpoolu, lpoolt; + unsigned pools_cnt; }; static void cleanup(void); @@ -108,11 +108,11 @@ char *make_ip(const char *host, const char *port); enum exit_reason { - FAIL_CMDLINE=1, - FAIL_INITIAL_CONN, - OUT_OF_MEMORY, - RECONNECT_FAIL, - SIGINT_REASON + FAIL_CMDLINE = 1, + FAIL_INITIAL_CONN, + OUT_OF_MEMORY, + RECONNECT_FAIL, + SIGINT_REASON }; static void exit_program(enum exit_reason reason, const char *func, unsigned line); @@ -121,41 +121,42 @@ #else #define EXIT_PROGRAM(r) exit_program(r, "", __LINE__); #endif -#define OOM_CHECK(p) do { if (!p) EXIT_PROGRAM(OUT_OF_MEMORY); } while (0) - +#define OOM_CHECK(p) \ + do { \ + if (!p) EXIT_PROGRAM(OUT_OF_MEMORY); \ + } while (0) static struct global_stats global; -static int curses_inited = 1; -static int maxystats=0; +static int curses_inited = 1; +static int maxystats = 0; static int detail_selected = -1; static int detail_exists(void) { - return global.num_clamd != 1; + return global.num_clamd != 1; } static int detail_is_selected(int idx) { - if (!detail_exists()) { - assert(idx == 0); - return 1; - } - return idx == detail_selected; + if (!detail_exists()) { + assert(idx == 0); + return 1; + } + return idx == detail_selected; } - /* ---------------------- NCurses routines -----------------*/ enum colors { - header_color=1, - version_color, - error_color, - value_color, - descr_color, - selected_color, - queue_header_color, - activ_color, - dim_color, - red_color, + header_color = 1, + version_color, + error_color, + value_color, + descr_color, + selected_color, + queue_header_color, + activ_color, + dim_color, + red_color, }; #define UPDATE_INTERVAL 2 @@ -168,14 +169,14 @@ #define DESCR_ATTR COLOR_PAIR(descr_color) #define ERROR_ATTR A_BOLD | COLOR_PAIR(error_color) -static WINDOW *header_window = NULL; +static WINDOW *header_window = NULL; static WINDOW *stats_head_window = NULL; -static WINDOW *stats_window = NULL; +static WINDOW *stats_window = NULL; static WINDOW *status_bar_window = NULL; -static WINDOW *mem_window = NULL; +static WINDOW *mem_window = NULL; static const char *status_bar_keys[10]; -static unsigned maxy=0, maxx=0; +static unsigned maxy = 0, maxx = 0; static char *queue_header = NULL; static char *clamd_header = NULL; @@ -194,247 +195,244 @@ static void resize(void) { - char *p; - unsigned new_maxy, new_maxx; - getmaxyx(stdscr, new_maxy, new_maxx); - if(new_maxy == maxy && new_maxx == maxx) - return; - maxx = new_maxx; - maxy = new_maxy; - free(queue_header); - free(clamd_header); - queue_header = malloc(maxx + 1); - OOM_CHECK(queue_header); - clamd_header = malloc(maxx + 1); - OOM_CHECK(clamd_header); - assert(clamd_header && queue_header); - strncpy(queue_header, global.num_clamd>1 ? CMDHEAD2 : CMDHEAD, maxx); - strncpy(clamd_header, SUMHEAD, maxx); - queue_header[maxx] = '\0'; - clamd_header[maxx] = '\0'; - p = queue_header + strlen(queue_header); - while(p < queue_header+maxx) - *p++ = ' '; - p = clamd_header + strlen(clamd_header); - while(p < clamd_header+maxx) - *p++ = ' '; + char *p; + unsigned new_maxy, new_maxx; + getmaxyx(stdscr, new_maxy, new_maxx); + if (new_maxy == maxy && new_maxx == maxx) + return; + maxx = new_maxx; + maxy = new_maxy; + free(queue_header); + free(clamd_header); + queue_header = malloc(maxx + 1); + OOM_CHECK(queue_header); + clamd_header = malloc(maxx + 1); + OOM_CHECK(clamd_header); + assert(clamd_header && queue_header); + strncpy(queue_header, global.num_clamd > 1 ? CMDHEAD2 : CMDHEAD, maxx); + strncpy(clamd_header, SUMHEAD, maxx); + queue_header[maxx] = '\0'; + clamd_header[maxx] = '\0'; + p = queue_header + strlen(queue_header); + while (p < queue_header + maxx) + *p++ = ' '; + p = clamd_header + strlen(clamd_header); + while (p < clamd_header + maxx) + *p++ = ' '; } static void rm_windows(void) { - if(header_window) { - delwin(header_window); - header_window = NULL; - } - if(mem_window) { - delwin(mem_window); - mem_window = NULL; - } - if(stats_window) { - delwin(stats_window); - stats_window = NULL; - } - if(stats_head_window) { - delwin(stats_head_window); - stats_head_window = NULL; - } - if(status_bar_window) { - delwin(status_bar_window); - status_bar_window = NULL; - } + if (header_window) { + delwin(header_window); + header_window = NULL; + } + if (mem_window) { + delwin(mem_window); + mem_window = NULL; + } + if (stats_window) { + delwin(stats_window); + stats_window = NULL; + } + if (stats_head_window) { + delwin(stats_head_window); + stats_head_window = NULL; + } + if (status_bar_window) { + delwin(status_bar_window); + status_bar_window = NULL; + } } - static void init_windows(int num_clamd) { - resize(); + resize(); - rm_windows(); - /* non-overlapping windows */ - header_window = subwin(stdscr, 1, maxx, 0, 0); - stats_head_window = subwin(stdscr, num_clamd+1, maxx, 1, 0); - maxystats = maxy-num_clamd-3; - stats_window = subwin(stdscr, maxystats, maxx, num_clamd+2, 0); - status_bar_window = subwin(stdscr, 1, maxx, maxy-1, 0); - /* memwindow overlaps, used only in details mode */ - mem_window = derwin(stats_window, 6, 41, 1, maxx-41); - touchwin(stdscr); - werase(stdscr); - refresh(); - memset(status_bar_keys, 0, sizeof(status_bar_keys)); - status_bar_keys[0] = "H - help"; - status_bar_keys[1] = "Q - quit"; - status_bar_keys[2] = "R - reset maximums"; - if (num_clamd > 1) { - status_bar_keys[3] = "^ - previous clamd"; - status_bar_keys[4] = "v - next clamd"; - } + rm_windows(); + /* non-overlapping windows */ + header_window = subwin(stdscr, 1, maxx, 0, 0); + stats_head_window = subwin(stdscr, num_clamd + 1, maxx, 1, 0); + maxystats = maxy - num_clamd - 3; + stats_window = subwin(stdscr, maxystats, maxx, num_clamd + 2, 0); + status_bar_window = subwin(stdscr, 1, maxx, maxy - 1, 0); + /* memwindow overlaps, used only in details mode */ + mem_window = derwin(stats_window, 6, 41, 1, maxx - 41); + touchwin(stdscr); + werase(stdscr); + refresh(); + memset(status_bar_keys, 0, sizeof(status_bar_keys)); + status_bar_keys[0] = "H - help"; + status_bar_keys[1] = "Q - quit"; + status_bar_keys[2] = "R - reset maximums"; + if (num_clamd > 1) { + status_bar_keys[3] = "^ - previous clamd"; + status_bar_keys[4] = "v - next clamd"; + } } static void init_ncurses(int num_clamd, int use_default) { - int default_bg = use_default ? DEFAULT_COLOR : COLOR_BLACK; - int default_fg = use_default ? DEFAULT_COLOR : COLOR_WHITE; - initscr(); - curses_inited = 1; - - start_color(); - keypad(stdscr, TRUE); /* enable keyboard mapping */ - nonl(); /* tell curses not to do NL->CR/NL on output */ - halfdelay(UPDATE_INTERVAL*10); /* timeout of 2s when waiting for input*/ - noecho(); /* dont echo input */ - curs_set(0); /* turn off cursor */ - if (use_default) - use_default_colors(); - - init_pair(header_color, COLOR_BLACK, COLOR_WHITE); - init_pair(version_color, default_fg, default_bg); - init_pair(error_color, COLOR_WHITE, COLOR_RED); - init_pair(value_color, COLOR_GREEN, default_bg); - init_pair(descr_color, COLOR_CYAN, default_bg); - init_pair(selected_color, COLOR_BLACK, COLOR_CYAN); - init_pair(queue_header_color, COLOR_BLACK, COLOR_GREEN); - init_pair(activ_color, COLOR_MAGENTA, default_bg); - init_pair(dim_color, COLOR_GREEN, default_bg); - init_pair(red_color, COLOR_RED, default_bg); + int default_bg = use_default ? DEFAULT_COLOR : COLOR_BLACK; + int default_fg = use_default ? DEFAULT_COLOR : COLOR_WHITE; + initscr(); + curses_inited = 1; + + start_color(); + keypad(stdscr, TRUE); /* enable keyboard mapping */ + nonl(); /* tell curses not to do NL->CR/NL on output */ + halfdelay(UPDATE_INTERVAL * 10); /* timeout of 2s when waiting for input*/ + noecho(); /* dont echo input */ + curs_set(0); /* turn off cursor */ + if (use_default) + use_default_colors(); + + init_pair(header_color, COLOR_BLACK, COLOR_WHITE); + init_pair(version_color, default_fg, default_bg); + init_pair(error_color, COLOR_WHITE, COLOR_RED); + init_pair(value_color, COLOR_GREEN, default_bg); + init_pair(descr_color, COLOR_CYAN, default_bg); + init_pair(selected_color, COLOR_BLACK, COLOR_CYAN); + init_pair(queue_header_color, COLOR_BLACK, COLOR_GREEN); + init_pair(activ_color, COLOR_MAGENTA, default_bg); + init_pair(dim_color, COLOR_GREEN, default_bg); + init_pair(red_color, COLOR_RED, default_bg); - init_windows(num_clamd); + init_windows(num_clamd); } static void win_start(WINDOW *win, enum colors col) { - wattrset(win, COLOR_PAIR(col)); - wbkgd(win, COLOR_PAIR(col)); - werase(win); -} - - -static void print_colored(WINDOW *win, const char *p) -{ - while(*p) { - wattron(win, DESCR_ATTR); - while(*p && !isdigit(*p)) - waddch(win, *p++); - wattroff(win, DESCR_ATTR); - wattron(win, VALUE_ATTR); - while(*p && isdigit(*p)) - waddch(win, *p++); - wattroff(win, VALUE_ATTR); - } + wattrset(win, COLOR_PAIR(col)); + wbkgd(win, COLOR_PAIR(col)); + werase(win); +} + +static void print_colored(WINDOW *win, const char *p) +{ + while (*p) { + wattron(win, DESCR_ATTR); + while (*p && !isdigit(*p)) + waddch(win, *p++); + wattroff(win, DESCR_ATTR); + wattron(win, VALUE_ATTR); + while (*p && isdigit(*p)) + waddch(win, *p++); + wattroff(win, VALUE_ATTR); + } } static void header(void) { - size_t i, x=0; - time_t t; + size_t i, x = 0; + time_t t; + win_start(header_window, header_color); + mvwprintw(header_window, 0, 0, " ClamdTOP version %s ", get_version()); + time(&t); + wprintw(header_window, "%s", ctime(&t)); + wrefresh(header_window); - win_start(header_window, header_color); - mvwprintw(header_window, 0, 0, " ClamdTOP version %s ", get_version()); - time(&t); - wprintw(header_window, "%s", ctime(&t)); - wrefresh(header_window); - -/* win_start(version_window, version_color); + /* win_start(version_window, version_color); mvwprintw(version_window, 0, 0, "Connected to: "); print_colored(version_window, clamd_version ? clamd_version : "Unknown"); wrefresh(version_window);*/ - werase(status_bar_window); - for(i=0;i= 2) { - z = x - 2; - } - mvwaddch(win, y, z, '>' | A_BLINK | COLOR_PAIR(red_color)); - move(y, z); - } + int y, x, z = 0; + unsigned len = 39; + unsigned start = 1; + unsigned activ = max ? ((live - idle) * (len - start - 2) + (max / 2)) / max : 0; + unsigned dim = max ? idle * (len - start - 2) / max : 0; + unsigned rem = len - activ - dim - start - 2; + + assert(activ + 2 < len && activ + dim + 2 < len && activ + dim + rem + 2 < len && "Invalid values"); + mvwaddch(win, i, start, '[' | A_BOLD); + wattron(win, A_BOLD | COLOR_PAIR(activ_color)); + for (i = 0; i < activ; i++) + waddch(win, '|'); + wattroff(win, A_BOLD | COLOR_PAIR(activ_color)); + wattron(win, A_DIM | COLOR_PAIR(dim_color)); + for (i = 0; i < dim; i++) + waddch(win, '|'); + wattroff(win, A_DIM | COLOR_PAIR(dim_color)); + for (i = 0; i < rem; i++) + waddch(win, ' '); + waddch(win, ']' | A_BOLD); + if (blink) { + getyx(win, y, x); + if ((x < 0) || (y < 0)) { + return; /* if getyx() failed, nevermind the blinking */ + } + if (x >= 2) { + z = x - 2; + } + mvwaddch(win, y, z, '>' | A_BLINK | COLOR_PAIR(red_color)); + move(y, z); + } } /* --------------------- Error handling ---------------------*/ -static int normal_exit = 0; +static int normal_exit = 0; static const char *exit_reason = NULL; -static const char *exit_func = NULL; -static unsigned exit_line = 0; +static const char *exit_func = NULL; +static unsigned exit_line = 0; static void cleanup(void) { - unsigned i; - if (curses_inited) { - if (status_bar_window) { - werase(status_bar_window); - wrefresh(status_bar_window); - } - rm_windows(); - endwin(); - } - curses_inited = 0; - for (i=0;itim < tb->tim) - return 1; - if(ta->tim > tb->tim) - return -1; - return 0; + const struct task *ta = a; + const struct task *tb = b; + if (ta->tim < tb->tim) + return 1; + if (ta->tim > tb->tim) + return -1; + return 0; } /* ----------- Socket routines ----------------------- */ @@ -493,23 +491,23 @@ #endif static void print_con_info(conn_t *conn, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (stats_head_window) { - char *buf = malloc(maxx); - OOM_CHECK(buf); - memset(buf, ' ', maxx); - vsnprintf(buf, maxx-1, fmt, ap); - buf[strlen(buf)] = ' '; - buf[maxx-1] = '\0'; - wattron(stats_head_window, ERROR_ATTR); - mvwprintw(stats_head_window, conn->line, 0, "%s", buf); - wattroff(stats_head_window, ERROR_ATTR); - wrefresh(stats_head_window); - free(buf); - } else - vfprintf(stdout, fmt, ap); - va_end(ap); + va_list ap; + va_start(ap, fmt); + if (stats_head_window) { + char *buf = malloc(maxx); + OOM_CHECK(buf); + memset(buf, ' ', maxx); + vsnprintf(buf, maxx - 1, fmt, ap); + buf[strlen(buf)] = ' '; + buf[maxx - 1] = '\0'; + wattron(stats_head_window, ERROR_ATTR); + mvwprintw(stats_head_window, conn->line, 0, "%s", buf); + wattroff(stats_head_window, ERROR_ATTR); + wrefresh(stats_head_window); + free(buf); + } else + vfprintf(stdout, fmt, ap); + va_end(ap); } char *get_ip(const char *ip) @@ -541,13 +539,13 @@ *p1 = '\0'; - p1 = strdup(dupip+1); + p1 = strdup(dupip + 1); free(dupip); return p1; } p1 = dupip; - i=0; + i = 0; while ((p1 = strchr(p1, ':'))) { i++; p1++; @@ -557,7 +555,7 @@ return dupip; if (i == 1) { - p1 = strchr(dupip, ':'); + p1 = strchr(dupip, ':'); *p1 = '\0'; return dupip; } @@ -568,7 +566,7 @@ char *get_port(const char *ip) { char *dupip, *p; - unsigned int offset=0; + unsigned int offset = 0; dupip = get_ip(ip); if (!(dupip)) @@ -579,7 +577,7 @@ p = (char *)ip + strlen(dupip) + offset; if (*p == ':') { - p = strdup(p+1); + p = strdup(p + 1); free(dupip); return p; } @@ -612,21 +610,21 @@ { int s = -1; struct timeval tv; - char *port=NULL; - char *pt = strdup(soname); + char *port = NULL; + char *pt = strdup(soname); const char *host = pt; - struct addrinfo hints, *res=NULL, *p; + struct addrinfo hints, *res = NULL, *p; int err; OOM_CHECK(pt); conn->tcp = 0; #ifndef _WIN32 - if(cli_is_abspath(soname) || (access(soname, F_OK) == 0)) { + if (cli_is_abspath(soname) || (access(soname, F_OK) == 0)) { struct sockaddr_un addr; s = socket(AF_UNIX, SOCK_STREAM, 0); - if(s < 0) { + if (s < 0) { perror("socket"); return -1; } @@ -648,9 +646,9 @@ #endif memset(&hints, 0x00, sizeof(struct addrinfo)); - hints.ai_family = AF_UNSPEC; + hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE; host = get_ip(soname); if (!(host)) @@ -658,7 +656,7 @@ port = get_port(soname); - conn->tcp=1; + conn->tcp = 1; print_con_info(conn, "Looking up: %s:%s\n", host, port ? port : "3310"); if ((err = getaddrinfo(host, (port != NULL) ? port : "3310", &hints, &res))) { @@ -702,7 +700,7 @@ free(port); conn->sd = s; gettimeofday(&conn->tv_conn, NULL); - tv.tv_sec = 30; + tv.tv_sec = 30; tv.tv_usec = 0; setsockopt(conn->sd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); return 0; @@ -737,438 +735,435 @@ static int send_string_noreconn(conn_t *conn, const char *cmd) { - assert(cmd); - assert(conn && conn->sd > 0); - return send(conn->sd, cmd, strlen(cmd), 0); + assert(cmd); + assert(conn && conn->sd > 0); + return send(conn->sd, cmd, strlen(cmd), 0); } static void send_string(conn_t *conn, const char *cmd) { - while(send_string_noreconn(conn, cmd) == -1) { - reconnect(conn); - } + while (send_string_noreconn(conn, cmd) == -1) { + reconnect(conn); + } } static int tries = 0; static void reconnect(conn_t *conn) { - if(++tries > 3) { - EXIT_PROGRAM(RECONNECT_FAIL); - } - if (conn->sd != -1) - close(conn->sd); - if (make_connection(conn->remote, conn) < 0) { - print_con_info(conn, "Unable to reconnect to %s: %s", conn->remote, strerror(errno)); - EXIT_PROGRAM(RECONNECT_FAIL); - } - tries = 0; + if (++tries > 3) { + EXIT_PROGRAM(RECONNECT_FAIL); + } + if (conn->sd != -1) + close(conn->sd); + if (make_connection(conn->remote, conn) < 0) { + print_con_info(conn, "Unable to reconnect to %s: %s", conn->remote, strerror(errno)); + EXIT_PROGRAM(RECONNECT_FAIL); + } + tries = 0; } static int recv_line(conn_t *conn, char *buf, size_t len) { - assert(len > 0); - assert(conn); - assert(buf); - - len--; - if (!len || conn->sd == -1) - return 0; - assert(conn->sd > 0); - while (len > 0) { - ssize_t nread = recv(conn->sd, buf, len, MSG_PEEK); - if (nread <= 0) { - print_con_info(conn, "%s: %s", conn->remote, strerror(errno)); - /* it could be a timeout, be nice and send an END */ - send_string_noreconn(conn, "nEND\n"); - close(conn->sd); - conn->sd = -1; - return 0; - } else { - char *p = memchr(buf, '\n', nread); - if (p) { - len = p - buf + 1; - } else - len = nread; - assert(len > 0); - assert(len <= (size_t)nread); - nread = recv(conn->sd, buf, len, 0); - if (nread == -1) - reconnect(conn); - else { - assert(nread >0 && (size_t)nread == len); - buf += nread; - } - if (p) - break; - } - } - *buf = '\0'; - return 1; + assert(len > 0); + assert(conn); + assert(buf); + + len--; + if (!len || conn->sd == -1) + return 0; + assert(conn->sd > 0); + while (len > 0) { + ssize_t nread = recv(conn->sd, buf, len, MSG_PEEK); + if (nread <= 0) { + print_con_info(conn, "%s: %s", conn->remote, strerror(errno)); + /* it could be a timeout, be nice and send an END */ + send_string_noreconn(conn, "nEND\n"); + close(conn->sd); + conn->sd = -1; + return 0; + } else { + char *p = memchr(buf, '\n', nread); + if (p) { + len = p - buf + 1; + } else + len = nread; + assert(len > 0); + assert(len <= (size_t)nread); + nread = recv(conn->sd, buf, len, 0); + if (nread == -1) + reconnect(conn); + else { + assert(nread > 0 && (size_t)nread == len); + buf += nread; + } + if (p) + break; + } + } + *buf = '\0'; + return 1; } static void output_queue(size_t line, ssize_t max) { - ssize_t i, j; - struct task *tasks = global.tasks; - struct task *filtered_tasks = calloc(global.n, sizeof(*filtered_tasks)); - OOM_CHECK(filtered_tasks); - for (i=0,j=0;i= j) - max = j; - else - --max; - if (max < 0) max = 0; - for(i=0;i cmde) - cmd[cmde - filtered_tasks[i].line] = '\0'; - if(filstart) { - ++filstart; - if (detail_selected == -1 && global.num_clamd > 1) - mvwprintw(stats_window, line + i, 0, "%2u %s", filtered_tasks[i].clamd_no, cmd + 1); - else - mvwprintw(stats_window, line + i, 0, " %s", cmd + 1); - mvwprintw(stats_window, line + i, 15, "%10.03fs", filtered_tasks[i].tim); - mvwprintw(stats_window, line + i, 30, "%s",filstart); - } - } - } - if (max < j) { - /* in summary mode we can only show a max amount of tasks */ - wattron(stats_window, A_DIM | COLOR_PAIR(header_color)); - mvwprintw(stats_window, line+i, 0, "*** %u more task(s) not shown ***", (unsigned)(j - max)); - wattroff(stats_window, A_DIM | COLOR_PAIR(header_color)); - } - free(filtered_tasks); + wattron(stats_window, COLOR_PAIR(queue_header_color)); + mvwprintw(stats_window, line++, 0, "%s", queue_header); + wattroff(stats_window, COLOR_PAIR(queue_header_color)); + if (max >= j) + max = j; + else + --max; + if (max < 0) max = 0; + for (i = 0; i < max; i++) { + char *cmde; + assert(tasks); + cmde = strchr(filtered_tasks[i].line, ' '); + if (cmde) { + char cmd[16]; + const char *filstart = strchr(cmde + 1, ' '); + strncpy(cmd, filtered_tasks[i].line, sizeof(cmd) - 1); + cmd[15] = '\0'; + if (filtered_tasks[i].line + 15 > cmde) + cmd[cmde - filtered_tasks[i].line] = '\0'; + if (filstart) { + ++filstart; + if (detail_selected == -1 && global.num_clamd > 1) + mvwprintw(stats_window, line + i, 0, "%2u %s", filtered_tasks[i].clamd_no, cmd + 1); + else + mvwprintw(stats_window, line + i, 0, " %s", cmd + 1); + mvwprintw(stats_window, line + i, 15, "%10.03fs", filtered_tasks[i].tim); + mvwprintw(stats_window, line + i, 30, "%s", filstart); + } + } + } + if (max < j) { + /* in summary mode we can only show a max amount of tasks */ + wattron(stats_window, A_DIM | COLOR_PAIR(header_color)); + mvwprintw(stats_window, line + i, 0, "*** %u more task(s) not shown ***", (unsigned)(j - max)); + wattroff(stats_window, A_DIM | COLOR_PAIR(header_color)); + } + free(filtered_tasks); } /* ---------------------- stats parsing routines ------------------- */ - -static void parse_queue(conn_t *conn, char* buf, size_t len, unsigned idx) +static void parse_queue(conn_t *conn, char *buf, size_t len, unsigned idx) { - do { - double tim; - const char *t = strchr(buf, ' '); - if(!t) - continue; - if(sscanf(t,"%lf", &tim) != 1) - continue; - ++global.n; - global.tasks = realloc(global.tasks, sizeof(*global.tasks)*global.n); - OOM_CHECK(global.tasks); - global.tasks[global.n-1].line = strdup(buf); - OOM_CHECK(global.tasks[global.n-1].line); - global.tasks[global.n-1].tim = tim; - global.tasks[global.n-1].clamd_no = idx + 1; - } while (recv_line(conn, buf, len) && buf[0] == '\t' && strcmp("END\n", buf) != 0); + do { + double tim; + const char *t = strchr(buf, ' '); + if (!t) + continue; + if (sscanf(t, "%lf", &tim) != 1) + continue; + ++global.n; + global.tasks = realloc(global.tasks, sizeof(*global.tasks) * global.n); + OOM_CHECK(global.tasks); + global.tasks[global.n - 1].line = strdup(buf); + OOM_CHECK(global.tasks[global.n - 1].line); + global.tasks[global.n - 1].tim = tim; + global.tasks[global.n - 1].clamd_no = idx + 1; + } while (recv_line(conn, buf, len) && buf[0] == '\t' && strcmp("END\n", buf) != 0); } static unsigned biggest_mem = 0; static void output_memstats(struct stats *stats) { - char buf[128]; - unsigned long totalmem; - int blink = 0; - - werase(mem_window); - if (stats->mem > 0 || (stats->mem >=0 && (stats->lpoolt > 0))) { - box(mem_window, 0, 0); - - if (stats->mem > 0) - snprintf(buf, sizeof(buf),"heap %4luM mmap %4luM unused %3luM", - stats->lheapu/1000, stats->lmmapu/1000, stats->lreleasable/1000); - else - snprintf(buf, sizeof(buf), "heap N/A mmap N/A unused N/A"); - mvwprintw(mem_window, 1, 1, "Mem: "); - print_colored(mem_window, buf); - - mvwprintw(mem_window, 2, 1, "Libc: "); - if (stats->mem > 0) - snprintf(buf, sizeof(buf),"used %4luM free %4luM total %4luM", - stats->ltotalu/1000, stats->ltotalf/1000, (stats->ltotalu+stats->ltotalf)/1000); - else - snprintf(buf, sizeof(buf), "used N/A free N/A total N/A"); - print_colored(mem_window, buf); - - mvwprintw(mem_window, 3, 1, "Pool: "); - snprintf(buf, sizeof(buf), "count %4u used %4luM total %4luM", - stats->pools_cnt, stats->lpoolu/1000, stats->lpoolt/1000); - print_colored(mem_window, buf); - - totalmem = stats->lheapu + stats->lmmapu + stats->lpoolt; - if(totalmem > biggest_mem) { - biggest_mem = totalmem; - blink = 1; - } - show_bar(mem_window, 4, totalmem, stats->lmmapu + stats->lreleasable + stats->lpoolt - stats->lpoolu, - biggest_mem, blink); - } - wrefresh(mem_window); + char buf[128]; + unsigned long totalmem; + int blink = 0; + + werase(mem_window); + if (stats->mem > 0 || (stats->mem >= 0 && (stats->lpoolt > 0))) { + box(mem_window, 0, 0); + + if (stats->mem > 0) + snprintf(buf, sizeof(buf), "heap %4luM mmap %4luM unused %3luM", + stats->lheapu / 1000, stats->lmmapu / 1000, stats->lreleasable / 1000); + else + snprintf(buf, sizeof(buf), "heap N/A mmap N/A unused N/A"); + mvwprintw(mem_window, 1, 1, "Mem: "); + print_colored(mem_window, buf); + + mvwprintw(mem_window, 2, 1, "Libc: "); + if (stats->mem > 0) + snprintf(buf, sizeof(buf), "used %4luM free %4luM total %4luM", + stats->ltotalu / 1000, stats->ltotalf / 1000, (stats->ltotalu + stats->ltotalf) / 1000); + else + snprintf(buf, sizeof(buf), "used N/A free N/A total N/A"); + print_colored(mem_window, buf); + + mvwprintw(mem_window, 3, 1, "Pool: "); + snprintf(buf, sizeof(buf), "count %4u used %4luM total %4luM", + stats->pools_cnt, stats->lpoolu / 1000, stats->lpoolt / 1000); + print_colored(mem_window, buf); + + totalmem = stats->lheapu + stats->lmmapu + stats->lpoolt; + if (totalmem > biggest_mem) { + biggest_mem = totalmem; + blink = 1; + } + show_bar(mem_window, 4, totalmem, stats->lmmapu + stats->lreleasable + stats->lpoolt - stats->lpoolu, + biggest_mem, blink); + } + wrefresh(mem_window); } static void parse_memstats(const char *line, struct stats *stats) { - double heapu, mmapu, totalu, totalf, releasable, pools_used, pools_total; + double heapu, mmapu, totalu, totalf, releasable, pools_used, pools_total; - if(sscanf(line, " heap %lfM mmap %lfM used %lfM free %lfM releasable %lfM pools %u pools_used %lfM pools_total %lfM", - &heapu, &mmapu, &totalu, &totalf, &releasable, &stats->pools_cnt, &pools_used, &pools_total) != 8) { - if (sscanf(line , " heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %lfM pools_total %lfM", - &stats->pools_cnt, &pools_used, &pools_total) != 3) { - stats->mem = -1; - return; - } - stats->lpoolu = pools_used*1000; - stats->lpoolt = pools_total*1000; - stats->mem = 0; - return; - } - stats->lheapu = heapu*1000; - stats->lmmapu = mmapu*1000; - stats->ltotalu = totalu*1000; - stats->ltotalf = totalf*1000; - stats->lreleasable = releasable*1000; - stats->lpoolu = pools_used*1000; - stats->lpoolt = pools_total*1000; - stats->mem = heapu + mmapu + pools_total; + if (sscanf(line, " heap %lfM mmap %lfM used %lfM free %lfM releasable %lfM pools %u pools_used %lfM pools_total %lfM", + &heapu, &mmapu, &totalu, &totalf, &releasable, &stats->pools_cnt, &pools_used, &pools_total) != 8) { + if (sscanf(line, " heap N/A mmap N/A used N/A free N/A releasable N/A pools %u pools_used %lfM pools_total %lfM", + &stats->pools_cnt, &pools_used, &pools_total) != 3) { + stats->mem = -1; + return; + } + stats->lpoolu = pools_used * 1000; + stats->lpoolt = pools_total * 1000; + stats->mem = 0; + return; + } + stats->lheapu = heapu * 1000; + stats->lmmapu = mmapu * 1000; + stats->ltotalu = totalu * 1000; + stats->ltotalf = totalf * 1000; + stats->lreleasable = releasable * 1000; + stats->lpoolu = pools_used * 1000; + stats->lpoolt = pools_total * 1000; + stats->mem = heapu + mmapu + pools_total; } static int output_stats(struct stats *stats, unsigned idx) { - char buf[128]; - char timbuf[15]; - int blink = 0; - size_t i= 0; - char mem[6]; - WINDOW *win = stats_head_window; - int sel = detail_is_selected(idx); - char *line = malloc(maxx+1); - - OOM_CHECK(line); - - if (stats->mem <= 0 || stats->stats_unsupp) { - strncpy(mem, "N/A", sizeof(mem)); - mem[sizeof(mem)-1]='\0'; - } - else { - char c; - double s; - if (stats->mem > 999.0) { - c = 'G'; - s = stats->mem / 1024.0; - } else { - c = 'M'; - s = stats->mem; - } - snprintf(mem, sizeof(mem), "%7.3f", s); - i = 4; - if (mem[i-1] == '.') i--; - mem[i++] = c; - mem[i] = '\0'; - } - i = idx+1; - - if (!stats->db_time.tm_year) { - strncpy(timbuf,"N/A",sizeof(timbuf)); - timbuf[sizeof(timbuf)-1]='\0'; - } - else - snprintf(timbuf, sizeof(timbuf), "%04u-%02u-%02u %02uh", - 1900 + stats->db_time.tm_year, - stats->db_time.tm_mon+1, - stats->db_time.tm_mday, - stats->db_time.tm_hour); - - memset(line, ' ', maxx+1); - if (!stats->stats_unsupp) { - snprintf(line, maxx-1, "%2u %02u:%02u:%02u %3u %3u %5u %5u %5s %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, - stats->live, stats->idle, - stats->current_q, stats->biggest_queue, - mem, - stats->remote, stats->engine_version, stats->db_version, timbuf); - } else { - snprintf(line, maxx-1, "%2u %02u:%02u:%02u N/A N/A N/A N/A N/A %-14s %-6s %5s %s", idx+1, stats->conn_hr, stats->conn_min, stats->conn_sec, - stats->remote, stats->engine_version, stats->db_version, timbuf); - } - line[maxx] = '\0'; - line[strlen(line)] = ' '; - if (sel) { - wattron(win, COLOR_PAIR(selected_color)); - } - mvwprintw(win, i, 0, "%s", line); - if (sel) { - wattroff(win, COLOR_PAIR(selected_color)); - } - win = stats_window; - i = 0; - if (sel && !stats->stats_unsupp) { - memset(line, ' ', maxx+1); - snprintf(line, maxx-1, "Details for Clamd version: %s", stats->version); - line[maxx] = '\0'; - line[strlen(line)]= ' '; - wattron(win, COLOR_PAIR(queue_header_color)); - mvwprintw(win, i++, 0, "%s", line); - wattroff(win, COLOR_PAIR(queue_header_color)); - mvwprintw(win, i++, 0, "Primary threads: "); - snprintf(buf, sizeof(buf), "live %3u idle %3u max %3u", stats->prim_live, stats->prim_idle, stats->prim_max); - print_colored(win, buf); - show_bar(win, i++, stats->prim_live, stats->prim_idle, stats->prim_max, 0); -/* mvwprintw(win, i++, 0, "Multiscan pool : "); + char buf[128]; + char timbuf[15]; + int blink = 0; + size_t i = 0; + char mem[6]; + WINDOW *win = stats_head_window; + int sel = detail_is_selected(idx); + char *line = malloc(maxx + 1); + + OOM_CHECK(line); + + if (stats->mem <= 0 || stats->stats_unsupp) { + strncpy(mem, "N/A", sizeof(mem)); + mem[sizeof(mem) - 1] = '\0'; + } else { + char c; + double s; + if (stats->mem > 999.0) { + c = 'G'; + s = stats->mem / 1024.0; + } else { + c = 'M'; + s = stats->mem; + } + snprintf(mem, sizeof(mem), "%7.3f", s); + i = 4; + if (mem[i - 1] == '.') i--; + mem[i++] = c; + mem[i] = '\0'; + } + i = idx + 1; + + if (!stats->db_time.tm_year) { + strncpy(timbuf, "N/A", sizeof(timbuf)); + timbuf[sizeof(timbuf) - 1] = '\0'; + } else + snprintf(timbuf, sizeof(timbuf), "%04u-%02u-%02u %02uh", + 1900 + stats->db_time.tm_year, + stats->db_time.tm_mon + 1, + stats->db_time.tm_mday, + stats->db_time.tm_hour); + + memset(line, ' ', maxx + 1); + if (!stats->stats_unsupp) { + snprintf(line, maxx - 1, "%2u %02u:%02u:%02u %3u %3u %5u %5u %5s %-14s %-6s %5s %s", idx + 1, stats->conn_hr, stats->conn_min, stats->conn_sec, + stats->live, stats->idle, + stats->current_q, stats->biggest_queue, + mem, + stats->remote, stats->engine_version, stats->db_version, timbuf); + } else { + snprintf(line, maxx - 1, "%2u %02u:%02u:%02u N/A N/A N/A N/A N/A %-14s %-6s %5s %s", idx + 1, stats->conn_hr, stats->conn_min, stats->conn_sec, + stats->remote, stats->engine_version, stats->db_version, timbuf); + } + line[maxx] = '\0'; + line[strlen(line)] = ' '; + if (sel) { + wattron(win, COLOR_PAIR(selected_color)); + } + mvwprintw(win, i, 0, "%s", line); + if (sel) { + wattroff(win, COLOR_PAIR(selected_color)); + } + win = stats_window; + i = 0; + if (sel && !stats->stats_unsupp) { + memset(line, ' ', maxx + 1); + snprintf(line, maxx - 1, "Details for Clamd version: %s", stats->version); + line[maxx] = '\0'; + line[strlen(line)] = ' '; + wattron(win, COLOR_PAIR(queue_header_color)); + mvwprintw(win, i++, 0, "%s", line); + wattroff(win, COLOR_PAIR(queue_header_color)); + mvwprintw(win, i++, 0, "Primary threads: "); + snprintf(buf, sizeof(buf), "live %3u idle %3u max %3u", stats->prim_live, stats->prim_idle, stats->prim_max); + print_colored(win, buf); + show_bar(win, i++, stats->prim_live, stats->prim_idle, stats->prim_max, 0); + /* mvwprintw(win, i++, 0, "Multiscan pool : "); snprintf(buf, sizeof(buf), "live %3u idle %3u max %3u", stats->live, stats->idle, stats->max); print_colored(win, buf); show_bar(win, i++, stats->live, stats->idle, stats->max, 0);*/ - blink = 0; - if(stats->current_q > stats->biggest_queue) { - stats->biggest_queue = stats->current_q; - blink = 1; - } - mvwprintw(win, i++, 0, "Queue:"); - snprintf(buf, sizeof(buf), "%6u items %6u max", stats->current_q, stats->biggest_queue); - print_colored(win, buf); - show_bar(win, i++, stats->current_q, 0, stats->biggest_queue, blink); - i += 2; - werase(mem_window); - output_memstats(stats); - } - free(line); - return i; + blink = 0; + if (stats->current_q > stats->biggest_queue) { + stats->biggest_queue = stats->current_q; + blink = 1; + } + mvwprintw(win, i++, 0, "Queue:"); + snprintf(buf, sizeof(buf), "%6u items %6u max", stats->current_q, stats->biggest_queue); + print_colored(win, buf); + show_bar(win, i++, stats->current_q, 0, stats->biggest_queue, blink); + i += 2; + werase(mem_window); + output_memstats(stats); + } + free(line); + return i; } static void output_all(void) { - unsigned i, stats_line=0; - werase(stats_head_window); - werase(stats_window); - wattron(stats_head_window, COLOR_PAIR(queue_header_color)); - mvwprintw(stats_head_window, 0, 0, "%s", clamd_header); - wattroff(stats_head_window, COLOR_PAIR(queue_header_color)); - for (i=0;i stats_line) - stats_line = j; - } - output_queue(stats_line, maxystats - stats_line-1); - wrefresh(stats_head_window); - wrefresh(stats_window); - if (detail_exists()) { - /* overlaps, must be done at the end */ - wrefresh(mem_window); - } + unsigned i, stats_line = 0; + werase(stats_head_window); + werase(stats_window); + wattron(stats_head_window, COLOR_PAIR(queue_header_color)); + mvwprintw(stats_head_window, 0, 0, "%s", clamd_header); + wattroff(stats_head_window, COLOR_PAIR(queue_header_color)); + for (i = 0; i < global.num_clamd; i++) { + unsigned j = output_stats(&global.all_stats[i], i); + if (j > stats_line) + stats_line = j; + } + output_queue(stats_line, maxystats - stats_line - 1); + wrefresh(stats_head_window); + wrefresh(stats_window); + if (detail_exists()) { + /* overlaps, must be done at the end */ + wrefresh(mem_window); + } } static void parse_stats(conn_t *conn, struct stats *stats, unsigned idx) { - char buf[1025]; - size_t j; - struct timeval tv; - unsigned conn_dt; - int primary = 0; - const char *pstart, *p, *vstart; - - if (conn->tcp) - stats->remote = conn->remote; - else - stats->remote = "local"; - - if (!conn->version) { - stats->engine_version = strdup("???"); - OOM_CHECK(stats->engine_version); - return; - } - p = pstart = vstart = strchr(conn->version, ' '); - if (!vstart) { - stats->engine_version = strdup("???"); - OOM_CHECK(stats->engine_version); - return; - } - /* find digit in version */ - while (*p && !isdigit(*p)) - p++; - /* rewind to first space or dash */ - while (p > pstart && *p && *p != ' ' && *p != '-') - p--; - if (*p) p++; - /* keep only base version, and cut -exp, and -gittags */ - pstart = p; - while (*p && *p != '-' && *p != '/') - p++; - - stats->engine_version = malloc(p - pstart+1); - OOM_CHECK(stats->engine_version); - - memcpy(stats->engine_version, pstart, p-pstart); - stats->engine_version[p-pstart] = '\0'; - - pstart = strchr(p, '/'); - if (!pstart) { - stats->db_version = strdup("????"); - OOM_CHECK(stats->db_version); - } else { - pstart++; - p = strchr(pstart, '/'); - if (!p) - p = pstart + strlen(pstart); - stats->db_version = malloc(p - pstart + 1); - OOM_CHECK(stats->db_version); - memcpy(stats->db_version, pstart, p-pstart); - stats->db_version[p-pstart] = '\0'; - if(*p) p++; - if (!*p || !strptime(p,"%a %b %d %H:%M:%S %Y", &stats->db_time)) { - memset(&stats->db_time, 0, sizeof(stats->db_time)); - } - } - if (maxx > 61 && strlen(stats->db_version) > (maxx-61)) { - stats->db_version[maxx-61] = '\0'; - } - - stats->version = vstart; /* for details view */ - gettimeofday(&tv, NULL); - tv.tv_sec -= conn->tv_conn.tv_sec; - tv.tv_usec -= conn->tv_conn.tv_usec; - conn_dt = tv.tv_sec + tv.tv_usec/1e6; - - stats->live = stats->idle = stats->max = 0; - stats->conn_hr = conn_dt/3600; - stats->conn_min = (conn_dt/60)%60; - stats->conn_sec = conn_dt%60; - stats->current_q = 0; - buf[sizeof(buf) - 1] = 0x0; - while(recv_line(conn, buf, sizeof(buf)-1) && strcmp("END\n",buf) != 0) { - char *val = strchr(buf, ':'); + char buf[1025]; + size_t j; + struct timeval tv; + unsigned conn_dt; + int primary = 0; + const char *pstart, *p, *vstart; + + if (conn->tcp) + stats->remote = conn->remote; + else + stats->remote = "local"; + + if (!conn->version) { + stats->engine_version = strdup("???"); + OOM_CHECK(stats->engine_version); + return; + } + p = pstart = vstart = strchr(conn->version, ' '); + if (!vstart) { + stats->engine_version = strdup("???"); + OOM_CHECK(stats->engine_version); + return; + } + /* find digit in version */ + while (*p && !isdigit(*p)) + p++; + /* rewind to first space or dash */ + while (p > pstart && *p && *p != ' ' && *p != '-') + p--; + if (*p) p++; + /* keep only base version, and cut -exp, and -gittags */ + pstart = p; + while (*p && *p != '-' && *p != '/') + p++; + + stats->engine_version = malloc(p - pstart + 1); + OOM_CHECK(stats->engine_version); + + memcpy(stats->engine_version, pstart, p - pstart); + stats->engine_version[p - pstart] = '\0'; + + pstart = strchr(p, '/'); + if (!pstart) { + stats->db_version = strdup("????"); + OOM_CHECK(stats->db_version); + } else { + pstart++; + p = strchr(pstart, '/'); + if (!p) + p = pstart + strlen(pstart); + stats->db_version = malloc(p - pstart + 1); + OOM_CHECK(stats->db_version); + memcpy(stats->db_version, pstart, p - pstart); + stats->db_version[p - pstart] = '\0'; + if (*p) p++; + if (!*p || !strptime(p, "%a %b %d %H:%M:%S %Y", &stats->db_time)) { + memset(&stats->db_time, 0, sizeof(stats->db_time)); + } + } + if (maxx > 61 && strlen(stats->db_version) > (maxx - 61)) { + stats->db_version[maxx - 61] = '\0'; + } - if(buf[0] == '\t') { - parse_queue(conn, buf, sizeof(buf)-1, idx); - continue; - } else if(val) - *val++ = '\0'; - if(!strcmp("MEMSTATS", buf)) { - parse_memstats(val, stats); - continue; - } - if(!strncmp("UNKNOWN COMMAND", buf, 15)) { - stats->stats_unsupp = 1; - break; - } - for(j=1;jversion = vstart; /* for details view */ + gettimeofday(&tv, NULL); + tv.tv_sec -= conn->tv_conn.tv_sec; + tv.tv_usec -= conn->tv_conn.tv_usec; + conn_dt = tv.tv_sec + tv.tv_usec / 1e6; + + stats->live = stats->idle = stats->max = 0; + stats->conn_hr = conn_dt / 3600; + stats->conn_min = (conn_dt / 60) % 60; + stats->conn_sec = conn_dt % 60; + stats->current_q = 0; + buf[sizeof(buf) - 1] = 0x0; + while (recv_line(conn, buf, sizeof(buf) - 1) && strcmp("END\n", buf) != 0) { + char *val = strchr(buf, ':'); + + if (buf[0] == '\t') { + parse_queue(conn, buf, sizeof(buf) - 1, idx); + continue; + } else if (val) + *val++ = '\0'; + if (!strcmp("MEMSTATS", buf)) { + parse_memstats(val, stats); + continue; + } + if (!strncmp("UNKNOWN COMMAND", buf, 15)) { + stats->stats_unsupp = 1; + break; + } + for (j = 1; j < strlen(buf); j++) + buf[j] = tolower(buf[j]); + /* mvwprintw(win, i, 0, "%s", buf); if(!val) { i++; continue; @@ -1176,58 +1171,58 @@ waddch(win, ':'); print_colored(win, val); i++;*/ - if(!strncmp("State",buf,5)) { - if(strstr(val, "PRIMARY")) { - /* primary thread pool */ - primary = 1; - } else { - /* multiscan pool */ - primary = 0; - } - } - if(!strcmp("Threads",buf)) { - unsigned live, idle, max; - if(sscanf(val, " live %u idle %u max %u", &live, &idle, &max) != 3) - continue; - if (primary) { - stats->prim_live = live; - stats->prim_idle = idle; - assert(!stats->prim_max && "There can be only one primary pool!"); - stats->prim_max = max; - } - stats->live += live; - stats->idle += idle; - stats->max += max; - } else if (!strcmp("Queue",buf)) { - unsigned len; - if(sscanf(val, "%u", &len) != 1) - continue; - stats->current_q += len; - } - } + if (!strncmp("State", buf, 5)) { + if (strstr(val, "PRIMARY")) { + /* primary thread pool */ + primary = 1; + } else { + /* multiscan pool */ + primary = 0; + } + } + if (!strcmp("Threads", buf)) { + unsigned live, idle, max; + if (sscanf(val, " live %u idle %u max %u", &live, &idle, &max) != 3) + continue; + if (primary) { + stats->prim_live = live; + stats->prim_idle = idle; + assert(!stats->prim_max && "There can be only one primary pool!"); + stats->prim_max = max; + } + stats->live += live; + stats->idle += idle; + stats->max += max; + } else if (!strcmp("Queue", buf)) { + unsigned len; + if (sscanf(val, "%u", &len) != 1) + continue; + stats->current_q += len; + } + } } static int read_version(conn_t *conn) { - char buf[1024]; - unsigned i; - if(!recv_line(conn, buf, sizeof(buf))) - return -1; - if (!strcmp(buf, "UNKNOWN COMMAND\n")) - return -2; - - conn->version = strdup(buf); - OOM_CHECK(conn->version); - for (i=0;iversion);i++) - if (conn->version[i] == '\n') - conn->version[i] = ' '; - return 0; + char buf[1024]; + unsigned i; + if (!recv_line(conn, buf, sizeof(buf))) + return -1; + if (!strcmp(buf, "UNKNOWN COMMAND\n")) + return -2; + + conn->version = strdup(buf); + OOM_CHECK(conn->version); + for (i = 0; i < strlen(conn->version); i++) + if (conn->version[i] == '\n') + conn->version[i] = ' '; + return 0; } static void sigint(int a) { UNUSEDPARAM(a); - EXIT_PROGRAM(SIGINT_REASON); + EXIT_PROGRAM(SIGINT_REASON); } static void help(void) @@ -1248,7 +1243,7 @@ printf("\n"); return; } -static int default_colors=0; +static int default_colors = 0; /* -------------------------- Initialization ---------------- */ static void setup_connections(int argc, char *argv[]) { @@ -1263,21 +1258,21 @@ EXIT_PROGRAM(FAIL_CMDLINE); } - if(optget(opts, "help")->enabled) { + if (optget(opts, "help")->enabled) { optfree(opts); help(); normal_exit = 1; exit(0); } - if(optget(opts, "version")->enabled) { + if (optget(opts, "version")->enabled) { printf("Clam AntiVirus Monitoring Tool %s\n", get_version()); optfree(opts); normal_exit = 1; exit(0); } - if(optget(opts, "defaultcolors")->enabled) + if (optget(opts, "defaultcolors")->enabled) default_colors = 1; memset(&global, 0, sizeof(global)); @@ -1290,7 +1285,7 @@ EXIT_PROGRAM(FAIL_CMDLINE); } - if((opt = optget(clamd_opts, "LocalSocket"))->enabled) { + if ((opt = optget(clamd_opts, "LocalSocket"))->enabled) { conn = strdup(opt->strarg); if (!conn) { fprintf(stderr, "Can't strdup LocalSocket value\n"); @@ -1314,19 +1309,21 @@ global.num_clamd = 1; } else { unsigned i = 0; - while (opts->filename[i]) { i++; } + while (opts->filename[i]) { + i++; + } global.num_clamd = i; } #ifdef _WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) { + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) { fprintf(stderr, "Error at WSAStartup(): %d\n", WSAGetLastError()); EXIT_PROGRAM(FAIL_INITIAL_CONN); } #endif /* clamdtop */ - puts( " __ ____"); + puts(" __ ____"); puts(" _____/ /___ _____ ___ ____/ / /_____ ____"); puts(" / ___/ / __ `/ __ `__ \\/ __ / __/ __ \\/ __ \\"); puts("/ /__/ / /_/ / / / / / / /_/ / /_/ /_/ / /_/ /"); @@ -1338,9 +1335,9 @@ global.conn = calloc(global.num_clamd, sizeof(*global.conn)); OOM_CHECK(global.conn); - for (i=0;i < global.num_clamd;i++) { - const char *soname = conn ? conn : opts->filename[i]; - global.conn[i].line = i+1; + for (i = 0; i < global.num_clamd; i++) { + const char *soname = conn ? conn : opts->filename[i]; + global.conn[i].line = i + 1; if (make_connection(soname, &global.conn[i]) < 0) { EXIT_PROGRAM(FAIL_INITIAL_CONN); } @@ -1356,146 +1353,146 @@ static void free_global_stats(void) { - unsigned i; - for (i=0;i<(unsigned)global.n;i++) { - free(global.tasks[i].line); - } - for (i=0;i 1) { - if (detail_selected == -1) - detail_selected = global.num_clamd-1; - else - --detail_selected; - } - break; - case KEY_DOWN: - if (global.num_clamd > 1) { - if (detail_selected == -1) - detail_selected = 0; - else { - if((unsigned)++detail_selected >= global.num_clamd) - detail_selected = -1; - } - } - break; - } - gettimeofday(&tv, NULL); - header(); - if(tv.tv_sec - tv_last.tv_sec >= MIN_INTERVAL) { - free_global_stats(); - for(i=0;ibiggest_queue; - memset(stats, 0, sizeof(*stats)); - stats->biggest_queue = biggest_q; - parse_stats(&global.conn[i], stats, i); - } - if (global.tasks) - qsort(global.tasks, global.n, sizeof(*global.tasks), tasks_compare); - tv_last = tv; - } - /* always show, so that screen resizes take effect instantly*/ - output_all(); - for(i=0;i 1) { + if (detail_selected == -1) + detail_selected = global.num_clamd - 1; + else + --detail_selected; + } + break; + case KEY_DOWN: + if (global.num_clamd > 1) { + if (detail_selected == -1) + detail_selected = 0; + else { + if ((unsigned)++detail_selected >= global.num_clamd) + detail_selected = -1; + } + } + break; + } + gettimeofday(&tv, NULL); + header(); + if (tv.tv_sec - tv_last.tv_sec >= MIN_INTERVAL) { + free_global_stats(); + for (i = 0; i < global.num_clamd; i++) { + unsigned biggest_q; + struct stats *stats = &global.all_stats[i]; + if (global.conn[i].sd != -1) + send_string(&global.conn[i], "nSTATS\n"); + biggest_q = stats->biggest_queue; + memset(stats, 0, sizeof(*stats)); + stats->biggest_queue = biggest_q; + parse_stats(&global.conn[i], stats, i); + } + if (global.tasks) + qsort(global.tasks, global.n, sizeof(*global.tasks), tasks_compare); + tv_last = tv; + } + /* always show, so that screen resizes take effect instantly*/ + output_all(); + for (i = 0; i < global.num_clamd; i++) { + if (global.conn[i].sd == -1) + reconnect(&global.conn[i]); + } + } while (toupper(ch = getch()) != 'Q'); + free_global_stats(); + normal_exit = 1; + return 0; } diff -Nru clamav-0.101.4+dfsg/clamonacc/Makefile.am clamav-0.102.1+dfsg/clamonacc/Makefile.am --- clamav-0.101.4+dfsg/clamonacc/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/Makefile.am 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,71 @@ +# +# Copyright (C) 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. +# +# Authors: Mickey Sola +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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. + +bin_PROGRAMS = clamonacc + +clamonacc_SOURCES = \ + $(top_srcdir)/shared/output.c \ + $(top_srcdir)/shared/output.h \ + $(top_srcdir)/shared/optparser.c \ + $(top_srcdir)/shared/optparser.h \ + $(top_srcdir)/shared/misc.c \ + $(top_srcdir)/shared/misc.h \ + $(top_srcdir)/shared/getopt.c \ + $(top_srcdir)/shared/getopt.h \ + $(top_srcdir)/shared/actions.c \ + $(top_srcdir)/shared/actions.h \ + clamonacc.c \ + clamonacc.h \ + ./client/client.c \ + ./client/client.h \ + ./client/protocol.c \ + ./client/protocol.h \ + ./client/communication.c \ + ./client/communication.h \ + ./inotif/inotif.c \ + ./inotif/inotif.h \ + ./fanotif/fanotif.c \ + ./fanotif/fanotif.h \ + ./inotif/hash.c \ + ./inotif/hash.h \ + ./misc/utils.c \ + ./misc/utils.h \ + ./misc/priv_fts.h \ + ./scan/thread.c \ + ./scan/thread.h \ + ./scan/queue.c \ + ./scan/queue.h \ + ./c-thread-pool/thpool.c \ + ./c-thread-pool/thpool.h + + +if !SYSTEM_LFS_FTS +clamonacc_SOURCES += ./misc/fts.c +endif + +AM_CFLAGS=@WERR_CFLAGS@ + +DEFS = @DEFS@ -DCL_NOLIBCLAMAV +LIBS = $(top_builddir)/libclamav/libclamav_internal_utils.la @CURL_LIBS@ @CLAMONACC_LIBS@ @THREAD_LIBS@ +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/clamonacc -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @CURL_CPPFLAGS@ @SSL_CPPFLAGS@ @CLAMONACC_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ + +AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=clamonacc$(EXEEXT) +CLEANFILES=*.gcda *.gcno + diff -Nru clamav-0.101.4+dfsg/clamonacc/Makefile.in clamav-0.102.1+dfsg/clamonacc/Makefile.in --- clamav-0.101.4+dfsg/clamonacc/Makefile.in 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,1158 @@ +# Makefile.in generated by automake 1.15.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2017 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# +# Copyright (C) 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. +# +# Authors: Mickey Sola +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# 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. + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +bin_PROGRAMS = clamonacc$(EXEEXT) +@SYSTEM_LFS_FTS_FALSE@am__append_1 = ./misc/fts.c +subdir = clamonacc +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ + $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ + $(top_srcdir)/m4/fdpassing.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/lib-prelude.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/llvm.m4 $(top_srcdir)/m4/ltargz.m4 \ + $(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ + $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ + $(top_srcdir)/m4/reorganization/build_tools.m4 \ + $(top_srcdir)/m4/reorganization/headers.m4 \ + $(top_srcdir)/m4/reorganization/c_options.m4 \ + $(top_srcdir)/m4/reorganization/compiler_checks.m4 \ + $(top_srcdir)/m4/reorganization/linker_checks.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/fuzz.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/functions.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/mpool.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/unit_tests.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/coverage.m4 \ + $(top_srcdir)/m4/reorganization/libs/xml.m4 \ + $(top_srcdir)/m4/reorganization/libs/openssl.m4 \ + $(top_srcdir)/m4/reorganization/libs/json.m4 \ + $(top_srcdir)/m4/reorganization/libs/pcre.m4 \ + $(top_srcdir)/m4/reorganization/libs/libmspack.m4 \ + $(top_srcdir)/m4/reorganization/libs/libz.m4 \ + $(top_srcdir)/m4/reorganization/libs/bzip.m4 \ + $(top_srcdir)/m4/reorganization/libs/unrar.m4 \ + $(top_srcdir)/m4/reorganization/libs/systemd.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/ipv6.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/dns.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ + $(top_srcdir)/m4/reorganization/milter/enable.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ + $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ + $(top_srcdir)/m4/reorganization/utility_checks/yp.m4 \ + $(top_srcdir)/m4/reorganization/usergroup.m4 \ + $(top_srcdir)/m4/reorganization/debug.m4 \ + $(top_srcdir)/m4/reorganization/customversion.m4 \ + $(top_srcdir)/m4/reorganization/nocache.m4 \ + $(top_srcdir)/m4/reorganization/dns.m4 \ + $(top_srcdir)/m4/reorganization/bigstack.m4 \ + $(top_srcdir)/m4/reorganization/dbdir.m4 \ + $(top_srcdir)/m4/reorganization/cfgdir.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/in_port_t.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/in_addr_t.m4 \ + $(top_srcdir)/m4/reorganization/os_checks.m4 \ + $(top_srcdir)/m4/reorganization/milter/check.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ + $(top_srcdir)/m4/reorganization/clamav_user.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/compiler_attribs.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/select.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/stat64.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/shift.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/features.m4 \ + $(top_srcdir)/m4/reorganization/clamdtop.m4 \ + $(top_srcdir)/m4/reorganization/distcheck.m4 \ + $(top_srcdir)/m4/reorganization/llvm.m4 \ + $(top_srcdir)/libclamav/c++/m4/llvm-opts.m4 \ + $(top_srcdir)/m4/reorganization/sha_collect.m4 \ + $(top_srcdir)/m4/reorganization/yara.m4 \ + $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ + $(top_srcdir)/m4/reorganization/prelude.m4 \ + $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ + $(top_srcdir)/m4/reorganization/libs/curl.m4 \ + $(top_srcdir)/m4/reorganization/substitutions.m4 \ + $(top_srcdir)/m4/reorganization/strni.m4 \ + $(top_srcdir)/m4/reorganization/types.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/clamav-config.h \ + $(top_builddir)/libclammspack/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__clamonacc_SOURCES_DIST = $(top_srcdir)/shared/output.c \ + $(top_srcdir)/shared/output.h $(top_srcdir)/shared/optparser.c \ + $(top_srcdir)/shared/optparser.h $(top_srcdir)/shared/misc.c \ + $(top_srcdir)/shared/misc.h $(top_srcdir)/shared/getopt.c \ + $(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/actions.c \ + $(top_srcdir)/shared/actions.h clamonacc.c clamonacc.h \ + ./client/client.c ./client/client.h ./client/protocol.c \ + ./client/protocol.h ./client/communication.c \ + ./client/communication.h ./inotif/inotif.c ./inotif/inotif.h \ + ./fanotif/fanotif.c ./fanotif/fanotif.h ./inotif/hash.c \ + ./inotif/hash.h ./misc/utils.c ./misc/utils.h \ + ./misc/priv_fts.h ./scan/thread.c ./scan/thread.h \ + ./scan/queue.c ./scan/queue.h ./c-thread-pool/thpool.c \ + ./c-thread-pool/thpool.h ./misc/fts.c +@SYSTEM_LFS_FTS_FALSE@am__objects_1 = fts.$(OBJEXT) +am_clamonacc_OBJECTS = output.$(OBJEXT) optparser.$(OBJEXT) \ + misc.$(OBJEXT) getopt.$(OBJEXT) actions.$(OBJEXT) \ + clamonacc.$(OBJEXT) client.$(OBJEXT) protocol.$(OBJEXT) \ + communication.$(OBJEXT) inotif.$(OBJEXT) fanotif.$(OBJEXT) \ + hash.$(OBJEXT) utils.$(OBJEXT) thread.$(OBJEXT) \ + queue.$(OBJEXT) thpool.$(OBJEXT) $(am__objects_1) +clamonacc_OBJECTS = $(am_clamonacc_OBJECTS) +clamonacc_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libclammspack +depcomp = $(SHELL) $(top_srcdir)/config/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(clamonacc_SOURCES) +DIST_SOURCES = $(am__clamonacc_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_CONFIGURE_FLAGS = @BUILD_CONFIGURE_FLAGS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFGDIR = @CFGDIR@ +CFLAGS = @CFLAGS@ +CHECK_CFLAGS = @CHECK_CFLAGS@ +CHECK_CPPFLAGS = @CHECK_CPPFLAGS@ +CHECK_LIBS = @CHECK_LIBS@ +CLAMAVGROUP = @CLAMAVGROUP@ +CLAMAVUSER = @CLAMAVUSER@ +CLAMAV_MILTER_CPPFLAGS = @CLAMAV_MILTER_CPPFLAGS@ +CLAMAV_MILTER_LIBS = @CLAMAV_MILTER_LIBS@ +CLAMBC_CPPFLAGS = @CLAMBC_CPPFLAGS@ +CLAMBC_LIBS = @CLAMBC_LIBS@ +CLAMCONF_CPPFLAGS = @CLAMCONF_CPPFLAGS@ +CLAMCONF_LIBS = @CLAMCONF_LIBS@ +CLAMDSCAN_CPPFLAGS = @CLAMDSCAN_CPPFLAGS@ +CLAMDSCAN_LIBS = @CLAMDSCAN_LIBS@ +CLAMDTOP_CPPFLAGS = @CLAMDTOP_CPPFLAGS@ +CLAMDTOP_LIBS = @CLAMDTOP_LIBS@ +CLAMD_CPPFLAGS = @CLAMD_CPPFLAGS@ +CLAMD_LIBS = @CLAMD_LIBS@ +CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ +CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ +CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ +CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ +CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ +CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ +CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ +CURSES_LIBS = @CURSES_LIBS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBDIR = @DBDIR@ +DEFINE_SF32_PREFIX = @DEFINE_SF32_PREFIX@ +DEFINE_SF64_PREFIX = @DEFINE_SF64_PREFIX@ +DEFS = @DEFS@ -DCL_NOLIBCLAMAV +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FRESHCLAM_CPPFLAGS = @FRESHCLAM_CPPFLAGS@ +FRESHCLAM_LIBS = @FRESHCLAM_LIBS@ +GCOV = @GCOV@ +GENERATE_WARNING = @GENERATE_WARNING@ +GENHTML = @GENHTML@ +GETENT = @GETENT@ +GPERF = @GPERF@ +GREP = @GREP@ +HAVE_STRNI = @HAVE_STRNI@ +HAVE_YARA = @HAVE_YARA@ +INCLTDL = @INCLTDL@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INT16_DEF = @INT16_DEF@ +INT32_DEF = @INT32_DEF@ +INT64_DEF = @INT64_DEF@ +INT8_DEF = @INT8_DEF@ +INT_TYPES_HEADER = @INT_TYPES_HEADER@ +JSON_CPPFLAGS = @JSON_CPPFLAGS@ +JSON_LDFLAGS = @JSON_LDFLAGS@ +JSON_LIBS = @JSON_LIBS@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LEX = @LEX@ +LEXLIB = @LEXLIB@ +LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ +LIBADD_DL = @LIBADD_DL@ +LIBADD_DLD_LINK = @LIBADD_DLD_LINK@ +LIBADD_DLOPEN = @LIBADD_DLOPEN@ +LIBADD_SHL_LOAD = @LIBADD_SHL_LOAD@ +LIBBZ2 = @LIBBZ2@ +LIBBZ2_PREFIX = @LIBBZ2_PREFIX@ +LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ +LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ +LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ +LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ +LIBLTDL = @LIBLTDL@ +LIBM = @LIBM@ +LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ +LIBMSPACK_LIBS = @LIBMSPACK_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBPRELUDE_CFLAGS = @LIBPRELUDE_CFLAGS@ +LIBPRELUDE_CONFIG = @LIBPRELUDE_CONFIG@ +LIBPRELUDE_CONFIG_PREFIX = @LIBPRELUDE_CONFIG_PREFIX@ +LIBPRELUDE_LDFLAGS = @LIBPRELUDE_LDFLAGS@ +LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@ +LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@ +LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@ +LIBS = $(top_builddir)/libclamav/libclamav_internal_utils.la @CURL_LIBS@ @CLAMONACC_LIBS@ @THREAD_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTDLDEPS = @LTDLDEPS@ +LTDLINCL = @LTDLINCL@ +LTDLOPEN = @LTDLOPEN@ +LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +LT_ARGZ_H = @LT_ARGZ_H@ +LT_CONFIG_H = @LT_CONFIG_H@ +LT_DLLOADERS = @LT_DLLOADERS@ +LT_DLPREOPEN = @LT_DLPREOPEN@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ +PCRE_LIBS = @PCRE_LIBS@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIGTOOL_CPPFLAGS = @SIGTOOL_CPPFLAGS@ +SSL_CPPFLAGS = @SSL_CPPFLAGS@ +SSL_LDFLAGS = @SSL_LDFLAGS@ +SSL_LIBS = @SSL_LIBS@ +STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +THREAD_LIBS = @THREAD_LIBS@ +TH_SAFE = @TH_SAFE@ +UINT16_DEF = @UINT16_DEF@ +UINT32_DEF = @UINT32_DEF@ +UINT64_DEF = @UINT64_DEF@ +UINT8_DEF = @UINT8_DEF@ +VERSION = @VERSION@ +VERSIONSCRIPTFLAG = @VERSIONSCRIPTFLAG@ +WERR_CFLAGS = @WERR_CFLAGS@ +WERR_CFLAGS_MILTER = @WERR_CFLAGS_MILTER@ +XML_CPPFLAGS = @XML_CPPFLAGS@ +XML_LIBS = @XML_LIBS@ +YACC = @YACC@ +YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +curl_config = @curl_config@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +llvmconfig = @llvmconfig@ +localedir = @localedir@ +localstatedir = @localstatedir@ +ltdl_LIBOBJS = @ltdl_LIBOBJS@ +ltdl_LTLIBOBJS = @ltdl_LTLIBOBJS@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pcreconfig = @pcreconfig@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sys_symbol_underscore = @sys_symbol_underscore@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ +clamonacc_SOURCES = $(top_srcdir)/shared/output.c \ + $(top_srcdir)/shared/output.h $(top_srcdir)/shared/optparser.c \ + $(top_srcdir)/shared/optparser.h $(top_srcdir)/shared/misc.c \ + $(top_srcdir)/shared/misc.h $(top_srcdir)/shared/getopt.c \ + $(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/actions.c \ + $(top_srcdir)/shared/actions.h clamonacc.c clamonacc.h \ + ./client/client.c ./client/client.h ./client/protocol.c \ + ./client/protocol.h ./client/communication.c \ + ./client/communication.h ./inotif/inotif.c ./inotif/inotif.h \ + ./fanotif/fanotif.c ./fanotif/fanotif.h ./inotif/hash.c \ + ./inotif/hash.h ./misc/utils.c ./misc/utils.h \ + ./misc/priv_fts.h ./scan/thread.c ./scan/thread.h \ + ./scan/queue.c ./scan/queue.h ./c-thread-pool/thpool.c \ + ./c-thread-pool/thpool.h $(am__append_1) +AM_CFLAGS = @WERR_CFLAGS@ +AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/clamonacc -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @CURL_CPPFLAGS@ @SSL_CPPFLAGS@ @CLAMONACC_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ +AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = clamonacc$(EXEEXT) +CLEANFILES = *.gcda *.gcno +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamonacc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign clamonacc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +installcheck-binPROGRAMS: $(bin_PROGRAMS) + bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \ + case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \ + *" $$p "* | *" $(srcdir)/$$p "*) continue;; \ + esac; \ + f=`echo "$$p" | \ + sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + for opt in --help --version; do \ + if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \ + 2>c$${pid}_.err &2; bad=1; fi; \ + done; \ + done; rm -f c$${pid}_.???; exit $$bad + +clamonacc$(EXEEXT): $(clamonacc_OBJECTS) $(clamonacc_DEPENDENCIES) $(EXTRA_clamonacc_DEPENDENCIES) + @rm -f clamonacc$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(clamonacc_OBJECTS) $(clamonacc_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/actions.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamonacc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/communication.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fanotif.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fts.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inotif.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/protocol.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thpool.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +output.o: $(top_srcdir)/shared/output.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.o -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/output.c' object='output.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.o `test -f '$(top_srcdir)/shared/output.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/output.c + +output.obj: $(top_srcdir)/shared/output.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT output.obj -MD -MP -MF $(DEPDIR)/output.Tpo -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/output.Tpo $(DEPDIR)/output.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/output.c' object='output.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o output.obj `if test -f '$(top_srcdir)/shared/output.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/output.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/output.c'; fi` + +optparser.o: $(top_srcdir)/shared/optparser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.o -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/optparser.c' object='optparser.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.o `test -f '$(top_srcdir)/shared/optparser.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/optparser.c + +optparser.obj: $(top_srcdir)/shared/optparser.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT optparser.obj -MD -MP -MF $(DEPDIR)/optparser.Tpo -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/optparser.Tpo $(DEPDIR)/optparser.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/optparser.c' object='optparser.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o optparser.obj `if test -f '$(top_srcdir)/shared/optparser.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/optparser.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/optparser.c'; fi` + +misc.o: $(top_srcdir)/shared/misc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.o -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/misc.c' object='misc.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.o `test -f '$(top_srcdir)/shared/misc.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/misc.c + +misc.obj: $(top_srcdir)/shared/misc.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT misc.obj -MD -MP -MF $(DEPDIR)/misc.Tpo -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/misc.Tpo $(DEPDIR)/misc.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/misc.c' object='misc.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi` + +getopt.o: $(top_srcdir)/shared/getopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.o -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/getopt.c' object='getopt.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.o `test -f '$(top_srcdir)/shared/getopt.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/getopt.c + +getopt.obj: $(top_srcdir)/shared/getopt.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT getopt.obj -MD -MP -MF $(DEPDIR)/getopt.Tpo -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/getopt.Tpo $(DEPDIR)/getopt.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/getopt.c' object='getopt.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o getopt.obj `if test -f '$(top_srcdir)/shared/getopt.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/getopt.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/getopt.c'; fi` + +actions.o: $(top_srcdir)/shared/actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT actions.o -MD -MP -MF $(DEPDIR)/actions.Tpo -c -o actions.o `test -f '$(top_srcdir)/shared/actions.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/actions.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/actions.Tpo $(DEPDIR)/actions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/actions.c' object='actions.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.o `test -f '$(top_srcdir)/shared/actions.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/actions.c + +actions.obj: $(top_srcdir)/shared/actions.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT actions.obj -MD -MP -MF $(DEPDIR)/actions.Tpo -c -o actions.obj `if test -f '$(top_srcdir)/shared/actions.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/actions.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/actions.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/actions.Tpo $(DEPDIR)/actions.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/actions.c' object='actions.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o actions.obj `if test -f '$(top_srcdir)/shared/actions.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/actions.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/actions.c'; fi` + +client.o: ./client/client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client.o -MD -MP -MF $(DEPDIR)/client.Tpo -c -o client.o `test -f './client/client.c' || echo '$(srcdir)/'`./client/client.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/client.Tpo $(DEPDIR)/client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/client.c' object='client.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client.o `test -f './client/client.c' || echo '$(srcdir)/'`./client/client.c + +client.obj: ./client/client.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client.obj -MD -MP -MF $(DEPDIR)/client.Tpo -c -o client.obj `if test -f './client/client.c'; then $(CYGPATH_W) './client/client.c'; else $(CYGPATH_W) '$(srcdir)/./client/client.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/client.Tpo $(DEPDIR)/client.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/client.c' object='client.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client.obj `if test -f './client/client.c'; then $(CYGPATH_W) './client/client.c'; else $(CYGPATH_W) '$(srcdir)/./client/client.c'; fi` + +protocol.o: ./client/protocol.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT protocol.o -MD -MP -MF $(DEPDIR)/protocol.Tpo -c -o protocol.o `test -f './client/protocol.c' || echo '$(srcdir)/'`./client/protocol.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/protocol.Tpo $(DEPDIR)/protocol.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/protocol.c' object='protocol.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o protocol.o `test -f './client/protocol.c' || echo '$(srcdir)/'`./client/protocol.c + +protocol.obj: ./client/protocol.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT protocol.obj -MD -MP -MF $(DEPDIR)/protocol.Tpo -c -o protocol.obj `if test -f './client/protocol.c'; then $(CYGPATH_W) './client/protocol.c'; else $(CYGPATH_W) '$(srcdir)/./client/protocol.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/protocol.Tpo $(DEPDIR)/protocol.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/protocol.c' object='protocol.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o protocol.obj `if test -f './client/protocol.c'; then $(CYGPATH_W) './client/protocol.c'; else $(CYGPATH_W) '$(srcdir)/./client/protocol.c'; fi` + +communication.o: ./client/communication.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication.o -MD -MP -MF $(DEPDIR)/communication.Tpo -c -o communication.o `test -f './client/communication.c' || echo '$(srcdir)/'`./client/communication.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/communication.Tpo $(DEPDIR)/communication.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/communication.c' object='communication.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication.o `test -f './client/communication.c' || echo '$(srcdir)/'`./client/communication.c + +communication.obj: ./client/communication.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication.obj -MD -MP -MF $(DEPDIR)/communication.Tpo -c -o communication.obj `if test -f './client/communication.c'; then $(CYGPATH_W) './client/communication.c'; else $(CYGPATH_W) '$(srcdir)/./client/communication.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/communication.Tpo $(DEPDIR)/communication.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./client/communication.c' object='communication.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication.obj `if test -f './client/communication.c'; then $(CYGPATH_W) './client/communication.c'; else $(CYGPATH_W) '$(srcdir)/./client/communication.c'; fi` + +inotif.o: ./inotif/inotif.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inotif.o -MD -MP -MF $(DEPDIR)/inotif.Tpo -c -o inotif.o `test -f './inotif/inotif.c' || echo '$(srcdir)/'`./inotif/inotif.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inotif.Tpo $(DEPDIR)/inotif.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./inotif/inotif.c' object='inotif.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inotif.o `test -f './inotif/inotif.c' || echo '$(srcdir)/'`./inotif/inotif.c + +inotif.obj: ./inotif/inotif.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT inotif.obj -MD -MP -MF $(DEPDIR)/inotif.Tpo -c -o inotif.obj `if test -f './inotif/inotif.c'; then $(CYGPATH_W) './inotif/inotif.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/inotif.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inotif.Tpo $(DEPDIR)/inotif.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./inotif/inotif.c' object='inotif.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o inotif.obj `if test -f './inotif/inotif.c'; then $(CYGPATH_W) './inotif/inotif.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/inotif.c'; fi` + +fanotif.o: ./fanotif/fanotif.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fanotif.o -MD -MP -MF $(DEPDIR)/fanotif.Tpo -c -o fanotif.o `test -f './fanotif/fanotif.c' || echo '$(srcdir)/'`./fanotif/fanotif.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fanotif.Tpo $(DEPDIR)/fanotif.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./fanotif/fanotif.c' object='fanotif.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fanotif.o `test -f './fanotif/fanotif.c' || echo '$(srcdir)/'`./fanotif/fanotif.c + +fanotif.obj: ./fanotif/fanotif.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fanotif.obj -MD -MP -MF $(DEPDIR)/fanotif.Tpo -c -o fanotif.obj `if test -f './fanotif/fanotif.c'; then $(CYGPATH_W) './fanotif/fanotif.c'; else $(CYGPATH_W) '$(srcdir)/./fanotif/fanotif.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fanotif.Tpo $(DEPDIR)/fanotif.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./fanotif/fanotif.c' object='fanotif.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fanotif.obj `if test -f './fanotif/fanotif.c'; then $(CYGPATH_W) './fanotif/fanotif.c'; else $(CYGPATH_W) '$(srcdir)/./fanotif/fanotif.c'; fi` + +hash.o: ./inotif/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash.o -MD -MP -MF $(DEPDIR)/hash.Tpo -c -o hash.o `test -f './inotif/hash.c' || echo '$(srcdir)/'`./inotif/hash.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hash.Tpo $(DEPDIR)/hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./inotif/hash.c' object='hash.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash.o `test -f './inotif/hash.c' || echo '$(srcdir)/'`./inotif/hash.c + +hash.obj: ./inotif/hash.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash.obj -MD -MP -MF $(DEPDIR)/hash.Tpo -c -o hash.obj `if test -f './inotif/hash.c'; then $(CYGPATH_W) './inotif/hash.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/hash.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/hash.Tpo $(DEPDIR)/hash.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./inotif/hash.c' object='hash.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash.obj `if test -f './inotif/hash.c'; then $(CYGPATH_W) './inotif/hash.c'; else $(CYGPATH_W) '$(srcdir)/./inotif/hash.c'; fi` + +utils.o: ./misc/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.o -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.o `test -f './misc/utils.c' || echo '$(srcdir)/'`./misc/utils.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./misc/utils.c' object='utils.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.o `test -f './misc/utils.c' || echo '$(srcdir)/'`./misc/utils.c + +utils.obj: ./misc/utils.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.obj -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.obj `if test -f './misc/utils.c'; then $(CYGPATH_W) './misc/utils.c'; else $(CYGPATH_W) '$(srcdir)/./misc/utils.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./misc/utils.c' object='utils.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.obj `if test -f './misc/utils.c'; then $(CYGPATH_W) './misc/utils.c'; else $(CYGPATH_W) '$(srcdir)/./misc/utils.c'; fi` + +thread.o: ./scan/thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.o -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.o `test -f './scan/thread.c' || echo '$(srcdir)/'`./scan/thread.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./scan/thread.c' object='thread.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.o `test -f './scan/thread.c' || echo '$(srcdir)/'`./scan/thread.c + +thread.obj: ./scan/thread.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thread.obj -MD -MP -MF $(DEPDIR)/thread.Tpo -c -o thread.obj `if test -f './scan/thread.c'; then $(CYGPATH_W) './scan/thread.c'; else $(CYGPATH_W) '$(srcdir)/./scan/thread.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thread.Tpo $(DEPDIR)/thread.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./scan/thread.c' object='thread.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.obj `if test -f './scan/thread.c'; then $(CYGPATH_W) './scan/thread.c'; else $(CYGPATH_W) '$(srcdir)/./scan/thread.c'; fi` + +queue.o: ./scan/queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT queue.o -MD -MP -MF $(DEPDIR)/queue.Tpo -c -o queue.o `test -f './scan/queue.c' || echo '$(srcdir)/'`./scan/queue.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/queue.Tpo $(DEPDIR)/queue.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./scan/queue.c' object='queue.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o queue.o `test -f './scan/queue.c' || echo '$(srcdir)/'`./scan/queue.c + +queue.obj: ./scan/queue.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT queue.obj -MD -MP -MF $(DEPDIR)/queue.Tpo -c -o queue.obj `if test -f './scan/queue.c'; then $(CYGPATH_W) './scan/queue.c'; else $(CYGPATH_W) '$(srcdir)/./scan/queue.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/queue.Tpo $(DEPDIR)/queue.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./scan/queue.c' object='queue.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o queue.obj `if test -f './scan/queue.c'; then $(CYGPATH_W) './scan/queue.c'; else $(CYGPATH_W) '$(srcdir)/./scan/queue.c'; fi` + +thpool.o: ./c-thread-pool/thpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thpool.o -MD -MP -MF $(DEPDIR)/thpool.Tpo -c -o thpool.o `test -f './c-thread-pool/thpool.c' || echo '$(srcdir)/'`./c-thread-pool/thpool.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thpool.Tpo $(DEPDIR)/thpool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./c-thread-pool/thpool.c' object='thpool.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thpool.o `test -f './c-thread-pool/thpool.c' || echo '$(srcdir)/'`./c-thread-pool/thpool.c + +thpool.obj: ./c-thread-pool/thpool.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thpool.obj -MD -MP -MF $(DEPDIR)/thpool.Tpo -c -o thpool.obj `if test -f './c-thread-pool/thpool.c'; then $(CYGPATH_W) './c-thread-pool/thpool.c'; else $(CYGPATH_W) '$(srcdir)/./c-thread-pool/thpool.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/thpool.Tpo $(DEPDIR)/thpool.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./c-thread-pool/thpool.c' object='thpool.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thpool.obj `if test -f './c-thread-pool/thpool.c'; then $(CYGPATH_W) './c-thread-pool/thpool.c'; else $(CYGPATH_W) '$(srcdir)/./c-thread-pool/thpool.c'; fi` + +fts.o: ./misc/fts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fts.o -MD -MP -MF $(DEPDIR)/fts.Tpo -c -o fts.o `test -f './misc/fts.c' || echo '$(srcdir)/'`./misc/fts.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fts.Tpo $(DEPDIR)/fts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./misc/fts.c' object='fts.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fts.o `test -f './misc/fts.c' || echo '$(srcdir)/'`./misc/fts.c + +fts.obj: ./misc/fts.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fts.obj -MD -MP -MF $(DEPDIR)/fts.Tpo -c -o fts.obj `if test -f './misc/fts.c'; then $(CYGPATH_W) './misc/fts.c'; else $(CYGPATH_W) '$(srcdir)/./misc/fts.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/fts.Tpo $(DEPDIR)/fts.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='./misc/fts.c' object='fts.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fts.obj `if test -f './misc/fts.c'; then $(CYGPATH_W) './misc/fts.c'; else $(CYGPATH_W) '$(srcdir)/./misc/fts.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: installcheck-binPROGRAMS + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ + clean-binPROGRAMS clean-generic clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installcheck-binPROGRAMS \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -Nru clamav-0.101.4+dfsg/clamonacc/c-thread-pool/thpool.c clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.c --- clamav-0.101.4+dfsg/clamonacc/c-thread-pool/thpool.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,551 @@ +/* ******************************** + * Author: Johan Hanssen Seferidis + * License: MIT + * Description: Library providing a threading pool where you can add + * work. For usage, check the thpool.h file or README.md + * + *//** @file thpool.h *//* + * + ********************************/ + +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include +#include +#include +#include +#if defined(__linux__) +#include +#endif + +#include "thpool.h" + +#ifdef THPOOL_DEBUG +#define THPOOL_DEBUG 1 +#else +#define THPOOL_DEBUG 0 +#endif + +#if !defined(DISABLE_PRINT) || defined(THPOOL_DEBUG) +#define err(str) fprintf(stderr, str) +#else +#define err(str) +#endif + +static volatile int threads_keepalive; +static volatile int threads_on_hold; + + + +/* ========================== STRUCTURES ============================ */ + + +/* Binary semaphore */ +typedef struct bsem { + pthread_mutex_t mutex; + pthread_cond_t cond; + int v; +} bsem; + + +/* Job */ +typedef struct job{ + struct job* prev; /* pointer to previous job */ + void (*function)(void* arg); /* function pointer */ + void* arg; /* function's argument */ +} job; + + +/* Job queue */ +typedef struct jobqueue{ + pthread_mutex_t rwmutex; /* used for queue r/w access */ + job *front; /* pointer to front of queue */ + job *rear; /* pointer to rear of queue */ + bsem *has_jobs; /* flag as binary semaphore */ + int len; /* number of jobs in queue */ +} jobqueue; + + +/* Thread */ +typedef struct thread{ + int id; /* friendly id */ + pthread_t pthread; /* pointer to actual thread */ + struct thpool_* thpool_p; /* access to thpool */ +} thread; + + +/* Threadpool */ +typedef struct thpool_{ + thread** threads; /* pointer to threads */ + volatile int num_threads_alive; /* threads currently alive */ + volatile int num_threads_working; /* threads currently working */ + pthread_mutex_t thcount_lock; /* used for thread count etc */ + pthread_cond_t threads_all_idle; /* signal to thpool_wait */ + jobqueue jobqueue; /* job queue */ +} thpool_; + + + + + +/* ========================== PROTOTYPES ============================ */ + + +static int thread_init(thpool_* thpool_p, struct thread** thread_p, int id); +static void* thread_do(struct thread* thread_p); +static void thread_hold(int sig_id); +static void thread_destroy(struct thread* thread_p); + +static int jobqueue_init(jobqueue* jobqueue_p); +static void jobqueue_clear(jobqueue* jobqueue_p); +static void jobqueue_push(jobqueue* jobqueue_p, struct job* newjob_p); +static struct job* jobqueue_pull(jobqueue* jobqueue_p); +static void jobqueue_destroy(jobqueue* jobqueue_p); + +static void bsem_init(struct bsem *bsem_p, int value); +static void bsem_reset(struct bsem *bsem_p); +static void bsem_post(struct bsem *bsem_p); +static void bsem_post_all(struct bsem *bsem_p); +static void bsem_wait(struct bsem *bsem_p); + + + + + +/* ========================== THREADPOOL ============================ */ + + +/* Initialise thread pool */ +struct thpool_* thpool_init(int num_threads){ + + threads_on_hold = 0; + threads_keepalive = 1; + + if (num_threads < 0){ + num_threads = 0; + } + + /* Make new thread pool */ + thpool_* thpool_p; + thpool_p = (struct thpool_*)malloc(sizeof(struct thpool_)); + if (thpool_p == NULL){ + err("thpool_init(): Could not allocate memory for thread pool\n"); + return NULL; + } + thpool_p->num_threads_alive = 0; + thpool_p->num_threads_working = 0; + + /* Initialise the job queue */ + if (jobqueue_init(&thpool_p->jobqueue) == -1){ + err("thpool_init(): Could not allocate memory for job queue\n"); + free(thpool_p); + return NULL; + } + + /* Make threads in pool */ + thpool_p->threads = (struct thread**)malloc(num_threads * sizeof(struct thread *)); + if (thpool_p->threads == NULL){ + err("thpool_init(): Could not allocate memory for threads\n"); + jobqueue_destroy(&thpool_p->jobqueue); + free(thpool_p); + return NULL; + } + + pthread_mutex_init(&(thpool_p->thcount_lock), NULL); + pthread_cond_init(&thpool_p->threads_all_idle, NULL); + + /* Thread init */ + int n; + for (n=0; nthreads[n], n); +#if THPOOL_DEBUG + printf("THPOOL_DEBUG: Created thread %d in pool \n", n); +#endif + } + + /* Wait for threads to initialize */ + while (thpool_p->num_threads_alive != num_threads) {} + + return thpool_p; +} + + +/* Add work to the thread pool */ +int thpool_add_work(thpool_* thpool_p, void (*function_p)(void*), void* arg_p){ + job* newjob; + + newjob=(struct job*)malloc(sizeof(struct job)); + if (newjob==NULL){ + err("thpool_add_work(): Could not allocate memory for new job\n"); + return -1; + } + + /* add function and argument */ + newjob->function=function_p; + newjob->arg=arg_p; + + /* add job to queue */ + jobqueue_push(&thpool_p->jobqueue, newjob); + + return 0; +} + + +/* Wait until all jobs have finished */ +void thpool_wait(thpool_* thpool_p){ + pthread_mutex_lock(&thpool_p->thcount_lock); + while (thpool_p->jobqueue.len || thpool_p->num_threads_working) { + pthread_cond_wait(&thpool_p->threads_all_idle, &thpool_p->thcount_lock); + } + pthread_mutex_unlock(&thpool_p->thcount_lock); +} + + +/* Destroy the threadpool */ +void thpool_destroy(thpool_* thpool_p){ + /* No need to destory if it's NULL */ + if (thpool_p == NULL) return ; + + volatile int threads_total = thpool_p->num_threads_alive; + + /* End each thread 's infinite loop */ + threads_keepalive = 0; + + /* Give one second to kill idle threads */ + double TIMEOUT = 1.0; + time_t start, end; + double tpassed = 0.0; + time (&start); + while (tpassed < TIMEOUT && thpool_p->num_threads_alive){ + bsem_post_all(thpool_p->jobqueue.has_jobs); + time (&end); + tpassed = difftime(end,start); + } + + /* Poll remaining threads */ + while (thpool_p->num_threads_alive){ + bsem_post_all(thpool_p->jobqueue.has_jobs); + sleep(1); + } + + /* Job queue cleanup */ + jobqueue_destroy(&thpool_p->jobqueue); + /* Deallocs */ + int n; + for (n=0; n < threads_total; n++){ + thread_destroy(thpool_p->threads[n]); + } + free(thpool_p->threads); + free(thpool_p); +} + + +/* Pause all threads in threadpool */ +void thpool_pause(thpool_* thpool_p) { + int n; + for (n=0; n < thpool_p->num_threads_alive; n++){ + pthread_kill(thpool_p->threads[n]->pthread, SIGUSR1); + } +} + + +/* Resume all threads in threadpool */ +void thpool_resume(thpool_* thpool_p) { + // resuming a single threadpool hasn't been + // implemented yet, meanwhile this supresses + // the warnings + (void)thpool_p; + + threads_on_hold = 0; +} + + +int thpool_num_threads_working(thpool_* thpool_p){ + return thpool_p->num_threads_working; +} + + + + + +/* ============================ THREAD ============================== */ + + +/* Initialize a thread in the thread pool + * + * @param thread address to the pointer of the thread to be created + * @param id id to be given to the thread + * @return 0 on success, -1 otherwise. + */ +static int thread_init (thpool_* thpool_p, struct thread** thread_p, int id){ + + *thread_p = (struct thread*)malloc(sizeof(struct thread)); + if (thread_p == NULL){ + err("thread_init(): Could not allocate memory for thread\n"); + return -1; + } + + (*thread_p)->thpool_p = thpool_p; + (*thread_p)->id = id; + + pthread_create(&(*thread_p)->pthread, NULL, (void *)thread_do, (*thread_p)); + pthread_detach((*thread_p)->pthread); + return 0; +} + + +/* Sets the calling thread on hold */ +static void thread_hold(int sig_id) { + (void)sig_id; + threads_on_hold = 1; + while (threads_on_hold){ + sleep(1); + } +} + + +/* What each thread is doing +* +* In principle this is an endless loop. The only time this loop gets interuppted is once +* thpool_destroy() is invoked or the program exits. +* +* @param thread thread that will run this function +* @return nothing +*/ +static void* thread_do(struct thread* thread_p){ + + /* Set thread name for profiling and debuging */ + char thread_name[128] = {0}; + sprintf(thread_name, "thread-pool-%d", thread_p->id); + +#if defined(__linux__) + /* Use prctl instead to prevent using _GNU_SOURCE flag and implicit declaration */ + prctl(PR_SET_NAME, thread_name); +#elif defined(__APPLE__) && defined(__MACH__) + pthread_setname_np(thread_name); +#else + err("thread_do(): pthread_setname_np is not supported on this system"); +#endif + + /* Assure all threads have been created before starting serving */ + thpool_* thpool_p = thread_p->thpool_p; + + /* Register signal handler */ + struct sigaction act; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = thread_hold; + if (sigaction(SIGUSR1, &act, NULL) == -1) { + err("thread_do(): cannot handle SIGUSR1"); + } + + /* Mark thread as alive (initialized) */ + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_alive += 1; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + while(threads_keepalive){ + + bsem_wait(thpool_p->jobqueue.has_jobs); + + if (threads_keepalive){ + + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_working++; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + /* Read job from queue and execute it */ + void (*func_buff)(void*); + void* arg_buff; + job* job_p = jobqueue_pull(&thpool_p->jobqueue); + if (job_p) { + func_buff = job_p->function; + arg_buff = job_p->arg; + func_buff(arg_buff); + free(job_p); + } + + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_working--; + if (!thpool_p->num_threads_working) { + pthread_cond_signal(&thpool_p->threads_all_idle); + } + pthread_mutex_unlock(&thpool_p->thcount_lock); + + } + } + pthread_mutex_lock(&thpool_p->thcount_lock); + thpool_p->num_threads_alive --; + pthread_mutex_unlock(&thpool_p->thcount_lock); + + return NULL; +} + + +/* Frees a thread */ +static void thread_destroy (thread* thread_p){ + free(thread_p); +} + + + + + +/* ============================ JOB QUEUE =========================== */ + + +/* Initialize queue */ +static int jobqueue_init(jobqueue* jobqueue_p){ + jobqueue_p->len = 0; + jobqueue_p->front = NULL; + jobqueue_p->rear = NULL; + + jobqueue_p->has_jobs = (struct bsem*)malloc(sizeof(struct bsem)); + if (jobqueue_p->has_jobs == NULL){ + return -1; + } + + pthread_mutex_init(&(jobqueue_p->rwmutex), NULL); + bsem_init(jobqueue_p->has_jobs, 0); + + return 0; +} + + +/* Clear the queue */ +static void jobqueue_clear(jobqueue* jobqueue_p){ + + while(jobqueue_p->len){ + free(jobqueue_pull(jobqueue_p)); + } + + jobqueue_p->front = NULL; + jobqueue_p->rear = NULL; + bsem_reset(jobqueue_p->has_jobs); + jobqueue_p->len = 0; + +} + + +/* Add (allocated) job to queue + */ +static void jobqueue_push(jobqueue* jobqueue_p, struct job* newjob){ + + pthread_mutex_lock(&jobqueue_p->rwmutex); + newjob->prev = NULL; + + switch(jobqueue_p->len){ + + case 0: /* if no jobs in queue */ + jobqueue_p->front = newjob; + jobqueue_p->rear = newjob; + break; + + default: /* if jobs in queue */ + jobqueue_p->rear->prev = newjob; + jobqueue_p->rear = newjob; + + } + jobqueue_p->len++; + + bsem_post(jobqueue_p->has_jobs); + pthread_mutex_unlock(&jobqueue_p->rwmutex); +} + + +/* Get first job from queue(removes it from queue) +<<<<<<< HEAD + * + * Notice: Caller MUST hold a mutex +======= +>>>>>>> da2c0fe45e43ce0937f272c8cd2704bdc0afb490 + */ +static struct job* jobqueue_pull(jobqueue* jobqueue_p){ + + pthread_mutex_lock(&jobqueue_p->rwmutex); + job* job_p = jobqueue_p->front; + + switch(jobqueue_p->len){ + + case 0: /* if no jobs in queue */ + break; + + case 1: /* if one job in queue */ + jobqueue_p->front = NULL; + jobqueue_p->rear = NULL; + jobqueue_p->len = 0; + break; + + default: /* if >1 jobs in queue */ + jobqueue_p->front = job_p->prev; + jobqueue_p->len--; + /* more than one job in queue -> post it */ + bsem_post(jobqueue_p->has_jobs); + + } + + pthread_mutex_unlock(&jobqueue_p->rwmutex); + return job_p; +} + + +/* Free all queue resources back to the system */ +static void jobqueue_destroy(jobqueue* jobqueue_p){ + jobqueue_clear(jobqueue_p); + free(jobqueue_p->has_jobs); +} + + + + + +/* ======================== SYNCHRONISATION ========================= */ + + +/* Init semaphore to 1 or 0 */ +static void bsem_init(bsem *bsem_p, int value) { + if (value < 0 || value > 1) { + err("bsem_init(): Binary semaphore can take only values 1 or 0"); + exit(1); + } + pthread_mutex_init(&(bsem_p->mutex), NULL); + pthread_cond_init(&(bsem_p->cond), NULL); + bsem_p->v = value; +} + + +/* Reset semaphore to 0 */ +static void bsem_reset(bsem *bsem_p) { + bsem_init(bsem_p, 0); +} + + +/* Post to at least one thread */ +static void bsem_post(bsem *bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + bsem_p->v = 1; + pthread_cond_signal(&bsem_p->cond); + pthread_mutex_unlock(&bsem_p->mutex); +} + + +/* Post to all threads */ +static void bsem_post_all(bsem *bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + bsem_p->v = 1; + pthread_cond_broadcast(&bsem_p->cond); + pthread_mutex_unlock(&bsem_p->mutex); +} + + +/* Wait on semaphore until semaphore has value 0 */ +static void bsem_wait(bsem* bsem_p) { + pthread_mutex_lock(&bsem_p->mutex); + while (bsem_p->v != 1) { + pthread_cond_wait(&bsem_p->cond, &bsem_p->mutex); + } + bsem_p->v = 0; + pthread_mutex_unlock(&bsem_p->mutex); +} diff -Nru clamav-0.101.4+dfsg/clamonacc/c-thread-pool/thpool.h clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.h --- clamav-0.101.4+dfsg/clamonacc/c-thread-pool/thpool.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/c-thread-pool/thpool.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,187 @@ +/********************************** + * @author Johan Hanssen Seferidis + * License: MIT + * + **********************************/ + +#ifndef _THPOOL_ +#define _THPOOL_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* =================================== API ======================================= */ + + +typedef struct thpool_* threadpool; + + +/** + * @brief Initialize threadpool + * + * Initializes a threadpool. This function will not return untill all + * threads have initialized successfully. + * + * @example + * + * .. + * threadpool thpool; //First we declare a threadpool + * thpool = thpool_init(4); //then we initialize it to 4 threads + * .. + * + * @param num_threads number of threads to be created in the threadpool + * @return threadpool created threadpool on success, + * NULL on error + */ +threadpool thpool_init(int num_threads); + + +/** + * @brief Add work to the job queue + * + * Takes an action and its argument and adds it to the threadpool's job queue. + * If you want to add to work a function with more than one arguments then + * a way to implement this is by passing a pointer to a structure. + * + * NOTICE: You have to cast both the function and argument to not get warnings. + * + * @example + * + * void print_num(int num){ + * printf("%d\n", num); + * } + * + * int main() { + * .. + * int a = 10; + * thpool_add_work(thpool, (void*)print_num, (void*)a); + * .. + * } + * + * @param threadpool threadpool to which the work will be added + * @param function_p pointer to function to add as work + * @param arg_p pointer to an argument + * @return 0 on successs, -1 otherwise. + */ +int thpool_add_work(threadpool, void (*function_p)(void*), void* arg_p); + + +/** + * @brief Wait for all queued jobs to finish + * + * Will wait for all jobs - both queued and currently running to finish. + * Once the queue is empty and all work has completed, the calling thread + * (probably the main program) will continue. + * + * Smart polling is used in wait. The polling is initially 0 - meaning that + * there is virtually no polling at all. If after 1 seconds the threads + * haven't finished, the polling interval starts growing exponentially + * untill it reaches max_secs seconds. Then it jumps down to a maximum polling + * interval assuming that heavy processing is being used in the threadpool. + * + * @example + * + * .. + * threadpool thpool = thpool_init(4); + * .. + * // Add a bunch of work + * .. + * thpool_wait(thpool); + * puts("All added work has finished"); + * .. + * + * @param threadpool the threadpool to wait for + * @return nothing + */ +void thpool_wait(threadpool); + + +/** + * @brief Pauses all threads immediately + * + * The threads will be paused no matter if they are idle or working. + * The threads return to their previous states once thpool_resume + * is called. + * + * While the thread is being paused, new work can be added. + * + * @example + * + * threadpool thpool = thpool_init(4); + * thpool_pause(thpool); + * .. + * // Add a bunch of work + * .. + * thpool_resume(thpool); // Let the threads start their magic + * + * @param threadpool the threadpool where the threads should be paused + * @return nothing + */ +void thpool_pause(threadpool); + + +/** + * @brief Unpauses all threads if they are paused + * + * @example + * .. + * thpool_pause(thpool); + * sleep(10); // Delay execution 10 seconds + * thpool_resume(thpool); + * .. + * + * @param threadpool the threadpool where the threads should be unpaused + * @return nothing + */ +void thpool_resume(threadpool); + + +/** + * @brief Destroy the threadpool + * + * This will wait for the currently active threads to finish and then 'kill' + * the whole threadpool to free up memory. + * + * @example + * int main() { + * threadpool thpool1 = thpool_init(2); + * threadpool thpool2 = thpool_init(2); + * .. + * thpool_destroy(thpool1); + * .. + * return 0; + * } + * + * @param threadpool the threadpool to destroy + * @return nothing + */ +void thpool_destroy(threadpool); + + +/** + * @brief Show currently working threads + * + * Working threads are the threads that are performing work (not idle). + * + * @example + * int main() { + * threadpool thpool1 = thpool_init(2); + * threadpool thpool2 = thpool_init(2); + * .. + * printf("Working threads: %d\n", thpool_num_threads_working(thpool1)); + * .. + * return 0; + * } + * + * @param threadpool the threadpool of interest + * @return integer number of threads working + */ +int thpool_num_threads_working(threadpool); + + +#ifdef __cplusplus +} +#endif + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/clamonacc.c clamav-0.102.1+dfsg/clamonacc/clamonacc.c --- clamav-0.101.4+dfsg/clamonacc/clamonacc.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/clamonacc.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifndef _WIN32 +#include +#endif +#include +#include +#if defined(FANOTIFY) +#include +#include +#endif + +#include "libclamav/clamav.h" +#include "libclamav/others.h" +#include "shared/output.h" +#include "shared/misc.h" +#include "shared/optparser.h" +#include "shared/actions.h" + +#include "clamonacc.h" +#include "client/client.h" +#include "fanotif/fanotif.h" +#include "inotif/inotif.h" +#include "scan/queue.h" + +pthread_t ddd_pid = 0; +pthread_t scan_queue_pid = 0; + +static void onas_handle_signals(); +static int startup_checks(struct onas_context *ctx); +static struct onas_context *g_ctx = NULL; + +static void onas_clamonacc_exit(int sig) +{ + logg("*Clamonacc: onas_clamonacc_exit(), signal %d\n", sig); + if (sig == 11) { + logg("!Clamonacc: clamonacc has experienced a fatal error, if you continue to see this error, please run clamonacc with --debug and report the issue and crash report to the developpers\n"); + } + + if (g_ctx) { + if (g_ctx->fan_fd) { + close(g_ctx->fan_fd); + } + g_ctx->fan_fd = 0; + } + + logg("*Clamonacc: attempting to stop event consumer thread ...\n"); + if (scan_queue_pid > 0) { + pthread_cancel(scan_queue_pid); + pthread_join(scan_queue_pid, NULL); + } + scan_queue_pid = 0; + + logg("*Clamonacc: attempting to stop ddd thread ... \n"); + if (ddd_pid > 0) { + pthread_cancel(ddd_pid); + pthread_join(ddd_pid, NULL); + } + ddd_pid = 0; + + logg("Clamonacc: stopped\n"); + onas_cleanup(g_ctx); + pthread_exit(NULL); +} + +int main(int argc, char **argv) +{ + const struct optstruct *opts; + const struct optstruct *clamdopts; + struct onas_context *ctx; + int ret = 0; + + /* Initialize context */ + ctx = onas_init_context(); + if (ctx == NULL) { + logg("!Clamonacc: can't initialize context\n"); + return 2; + } + + /* Parse out all our command line options */ + opts = optparse(NULL, argc, argv, 1, OPT_CLAMONACC, OPT_CLAMSCAN, NULL); + if (opts == NULL) { + logg("!Clamonacc: can't parse command line options\n"); + return 2; + } + ctx->opts = opts; + + /* And our config file options */ + clamdopts = optparse(optget(opts, "config-file")->strarg, 0, NULL, 1, OPT_CLAMD, 0, NULL); + if (clamdopts == NULL) { + logg("!Clamonacc: can't parse clamd configuration file %s\n", optget(opts, "config-file")->strarg); + return 2; + } + ctx->clamdopts = clamdopts; + + /* Make sure we're good to begin spinup */ + ret = startup_checks(ctx); + if (ret) { + goto clean_up; + } + +#ifndef _WIN32 + /* Daemonize if sanity checks are good to go */ + if (!optget(ctx->opts, "foreground")->enabled) { + if (-1 == daemonize()) { + logg("!Clamonacc: could not daemonize\n"); + return 2; + } + } +#endif + + /* Setup our client */ + switch (onas_setup_client(&ctx)) { + case CL_SUCCESS: + if (CL_SUCCESS == onas_check_client_connection(&ctx)) { + break; + } + case CL_BREAK: + ret = 0; + logg("*Clamonacc: not setting up client\n"); + goto clean_up; + break; + case CL_EARG: + default: + logg("!Clamonacc: can't setup client\n"); + ret = 2; + goto clean_up; + break; + } + + /* Setup our event queue */ + ctx->maxthreads = optget(ctx->clamdopts, "OnAccessMaxThreads")->numarg; + + switch (onas_scan_queue_start(&ctx)) { + case CL_SUCCESS: + break; + case CL_BREAK: + case CL_EARG: + case CL_ECREAT: + default: + ret = 2; + logg("!Clamonacc: can't setup event consumer queue\n"); + goto clean_up; + break; + } + +#if defined(FANOTIFY) + /* Setup fanotify */ + switch (onas_setup_fanotif(&ctx)) { + case CL_SUCCESS: + break; + case CL_BREAK: + ret = 0; + goto clean_up; + break; + case CL_EARG: + default: + mprintf("!Clamonacc: can't setup fanotify\n"); + ret = 2; + goto clean_up; + break; + } + + if (ctx->ddd_enabled) { + /* Setup inotify and kickoff DDD system */ + switch (onas_enable_inotif_ddd(&ctx)) { + case CL_SUCCESS: + break; + case CL_BREAK: + ret = 0; + goto clean_up; + break; + case CL_EARG: + default: + mprintf("!Clamonacc: can't setup fanotify\n"); + ret = 2; + goto clean_up; + break; + } + } +#else + mprintf("!Clamonacc: currently, this application only runs on linux systems with fanotify enabled\n"); + goto clean_up; +#endif + + /* Setup signal handling */ + g_ctx = ctx; + onas_handle_signals(); + + logg("*Clamonacc: beginning event loops\n"); + /* Kick off event loop(s) */ + ret = onas_start_eloop(&ctx); + + /* Clean up */ +clean_up: + onas_cleanup(ctx); + exit(ret); +} + +static void onas_handle_signals() +{ + sigset_t sigset; + struct sigaction act; + + /* ignore all signals except SIGUSR1 */ + sigfillset(&sigset); + sigdelset(&sigset, SIGUSR1); + sigdelset(&sigset, SIGUSR2); + /* The behavior of a process is undefined after it ignores a + * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ + sigdelset(&sigset, SIGFPE); + sigdelset(&sigset, SIGILL); + sigdelset(&sigset, SIGSEGV); + sigdelset(&sigset, SIGINT); + sigdelset(&sigset, SIGTERM); +#ifdef SIGBUS + sigdelset(&sigset, SIGBUS); +#endif + pthread_sigmask(SIG_SETMASK, &sigset, NULL); + memset(&act, 0, sizeof(struct sigaction)); + act.sa_handler = onas_clamonacc_exit; + sigfillset(&(act.sa_mask)); + sigaction(SIGUSR2, &act, NULL); + sigaction(SIGTERM, &act, NULL); + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGINT, &act, NULL); +} + +struct onas_context *onas_init_context(void) +{ + struct onas_context *ctx = (struct onas_context *)cli_malloc(sizeof(struct onas_context)); + if (NULL == ctx) { + return NULL; + } + + memset(ctx, 0, sizeof(struct onas_context)); + return ctx; +} + +cl_error_t onas_check_client_connection(struct onas_context **ctx) +{ + + cl_error_t err = CL_SUCCESS; + + /* 0 local, non-zero remote, errno set on error */ + (*ctx)->isremote = onas_check_remote(ctx, &err); + if (CL_SUCCESS == err) { + logg("*Clamonacc: "); + (*ctx)->isremote ? logg("*daemon is remote\n") : logg("*daemon is local\n"); + } + return err ? CL_EACCES : CL_SUCCESS; +} + +int onas_start_eloop(struct onas_context **ctx) +{ + int ret = 0; + + if (!ctx || !*ctx) { + mprintf("!Clamonacc: unable to start clamonacc. (bad context)\n"); + return CL_EARG; + } + +#if defined(FANOTIFY) + ret = onas_fan_eloop(ctx); +#endif + + return ret; +} + +static int startup_checks(struct onas_context *ctx) +{ + +#if defined(FANOTIFY) + char faerr[128]; +#endif + int ret = 0; + cl_error_t err = CL_SUCCESS; + + if (optget(ctx->opts, "help")->enabled) { + help(); + ret = 2; + goto done; + } + + if (optget(ctx->opts, "version")->enabled) { + onas_print_server_version(&ctx); + ret = 2; + goto done; + } + +#if defined(FANOTIFY) + ctx->fan_fd = fanotify_init(FAN_CLASS_CONTENT | FAN_UNLIMITED_QUEUE | FAN_UNLIMITED_MARKS, O_LARGEFILE | O_RDONLY); + if (ctx->fan_fd < 0) { + logg("!Clamonacc: fanotify_init failed: %s\n", cli_strerror(errno, faerr, sizeof(faerr))); + if (errno == EPERM) { + logg("!Clamonacc: clamonacc must have elevated permissions ... exiting ...\n"); + } + ret = 2; + goto done; + } +#endif + + if (curl_global_init(CURL_GLOBAL_NOTHING)) { + ret = 2; + goto done; + } + + if (0 == onas_check_remote(&ctx, &err)) { + + if (CL_SUCCESS != err) { + logg("!Clamonacc: daemon is local, but a connection could not be established\n"); + ret = 2; + goto done; + } + + if (!optget(ctx->clamdopts, "OnAccessExcludeUID")->enabled && + !optget(ctx->clamdopts, "OnAccessExcludeUname")->enabled && !optget(ctx->clamdopts, "OnAccessExcludeRootUID")->enabled) { + logg("!Clamonacc: at least one of OnAccessExcludeUID, OnAccessExcludeUname, or OnAccessExcludeRootUID must be specified ... it is reccomended you exclude the clamd instance UID or uname to prevent infinite event scanning loops\n"); + ret = 2; + goto done; + } + } +done: + return ret; +} + +void help(void) +{ + mprintf_stdout = 1; + + mprintf("\n"); + mprintf(" ClamAV: On Access Scanning Application and Client %s\n", get_version()); + mprintf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n"); + mprintf(" (C) 2019 Cisco Systems, Inc.\n"); + mprintf("\n"); + mprintf(" clamonacc [options] [file/directory/-]\n"); + mprintf("\n"); + mprintf(" --help -h Show this help\n"); + mprintf(" --version -V Print version number and exit\n"); + mprintf(" --verbose -v Be verbose\n"); + mprintf(" --log=FILE -l FILE Save scanning output to FILE\n"); + mprintf(" --foreground -F Output to foreground and do not daemonize\n"); + mprintf(" --watch-list=FILE -w FILE Watch directories from FILE\n"); + mprintf(" --exclude-list=FILE -e FILE Exclude directories from FILE\n"); + mprintf(" --remove Remove infected files. Be careful!\n"); + mprintf(" --move=DIRECTORY Move infected files into DIRECTORY\n"); + mprintf(" --copy=DIRECTORY Copy infected files into DIRECTORY\n"); + mprintf(" --config-file=FILE Read configuration from FILE.\n"); + mprintf(" --allmatch -z Continue scanning within file after finding a match.\n"); + mprintf(" --fdpass Pass filedescriptor to clamd (useful if clamd is running as a different user)\n"); + mprintf(" --stream Force streaming files to clamd (for debugging and unit testing)\n"); + mprintf("\n"); + + exit(0); +} + +void onas_cleanup(struct onas_context *ctx) +{ + onas_context_cleanup(ctx); + logg_close(); +} + +void onas_context_cleanup(struct onas_context *ctx) +{ + close(ctx->fan_fd); + optfree((struct optstruct *)ctx->opts); + optfree((struct optstruct *)ctx->clamdopts); + ctx->opts = NULL; + ctx->clamdopts = NULL; + free(ctx); +} diff -Nru clamav-0.101.4+dfsg/clamonacc/clamonacc.h clamav-0.102.1+dfsg/clamonacc/clamonacc.h --- clamav-0.101.4+dfsg/clamonacc/clamonacc.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/clamonacc.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2007-2013 Sourcefire, Inc. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_CLAMONACC_H +#define __ONAS_CLAMONACC_H + +#include "libclamav/clamav.h" + +#ifndef ONAS_DEBUG +#define ONAS_DEBUG +#endif +/* dev only switch for very noisy output */ +#undef ONAS_DEBUG + +#ifndef HAVE_ATTRIB_PACKED +#define __attribute__(x) +#endif +#ifdef HAVE_PRAGMA_PACK +#pragma pack(1) +#endif +#ifdef HAVE_PRAGMA_PACK_HPPA +#pragma pack 1 +#endif + +struct onas_context { + const struct optstruct *opts; + const struct optstruct *clamdopts; + + int printinfected; + int maxstream; + + uint32_t ddd_enabled; + + int fan_fd; + uint64_t fan_mask; + uint8_t retry_on_error; + uint8_t retry_attempts; + uint8_t deny_on_error; + + uint64_t sizelimit; + uint64_t extinfo; + + int scantype; + int isremote; + int session; + int timeout; + + int64_t portnum; + + int32_t maxthreads; +} __attribute__((packed)); + +#ifdef HAVE_PRAGMA_PACK +#pragma pack() +#endif +#ifdef HAVE_PRAGMA_PACK_HPPA +#pragma pack +#endif + +struct onas_context *onas_init_context(void); +void onas_cleanup(struct onas_context *ctx); +void onas_context_cleanup(struct onas_context *ctx); +cl_error_t onas_check_client_connection(struct onas_context **ctx); +int onas_start_eloop(struct onas_context **ctx); +void help(void); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/client/client.c clamav-0.102.1+dfsg/clamonacc/client/client.c --- clamav-0.101.4+dfsg/clamonacc/client/client.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/client.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2015-2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Tomasz Kojm, aCaB, Mickey Sola + * + * 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 +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_LIMITS_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_UIO_H +#include +#endif + +#include "libclamav/clamav.h" +#include "shared/optparser.h" +#include "shared/output.h" +#include "shared/misc.h" +#include "shared/actions.h" + +#include "libclamav/str.h" +#include "libclamav/others.h" + +#include "communication.h" +#include "client.h" +#include "protocol.h" + +#include "../clamonacc.h" + +struct sockaddr_un nixsock; + +void onas_print_server_version(struct onas_context **ctx) +{ + if (onas_get_clamd_version(ctx)) { + /* can't get version from server, fallback */ + printf("ClamAV %s\n", get_version()); + } +} + +/* Inits the communication layer + * Returns 0 if clamd is local, non zero if clamd is remote */ +int onas_check_remote(struct onas_context **ctx, cl_error_t *err) +{ + int s, ret; + const struct optstruct *opt; + CURL *curl; + CURLcode curlcode; + char *ipaddr = NULL; + struct addrinfo hints, *info, *p; + int res; + int64_t timeout; + + timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; + + *err = CL_SUCCESS; + +#ifndef _WIN32 + if ((opt = optget((*ctx)->clamdopts, "LocalSocket"))->enabled) { + opt = optget((*ctx)->clamdopts, "LocalSocket"); + (*ctx)->portnum = 0; + ret = 0; + } else { + opt = optget((*ctx)->clamdopts, "TCPAddr"); + (*ctx)->portnum = optget((*ctx)->clamdopts, "TCPSocket")->numarg; + ret = 1; + } +#else + if (!(opt = optget((*ctx)->clamdopts, "TCPSocket"))->enabled) { + return 0; + } +#endif + + while (opt) { + + if (opt->strarg) { + ipaddr = (!strcmp(opt->strarg, "any") ? NULL : opt->strarg); + } + + if (NULL == ipaddr) { + logg("!ClamClient: Clamonacc does not support binding to INADDR_ANY, \ + please specify an address with TCPAddr in your clamd.conf config file\n"); + *err = CL_EARG; + return ret; + } + + curlcode = onas_curl_init(&curl, ipaddr, (*ctx)->portnum, timeout); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not init curl, %s\n", curl_easy_strerror(curlcode)); + *err = CL_EARG; + return ret; + } + + curlcode = curl_easy_perform(curl); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not connect to remote clam daemon, %s\n", curl_easy_strerror(curlcode)); + *err = CL_EARG; + return ret; + } + +#ifndef ONAS_DEBUG + if (onas_sendln(curl, "zPING", 5, timeout)) { + logg("!ClamClient: could not ping clamd, %s\n", curl_easy_strerror(curlcode)); + *err = CL_EARG; + curl_easy_cleanup(curl); + return ret; + } +#endif + + curl_easy_cleanup(curl); + + opt = opt->nextarg; + } + + return ret; +} + +/** + * @brief initialises a curl connection for the onaccess client; curl must be initialised globally before use + * + * @param curl pointer to the curl object to be used in the connection attempt + * @param ipaddr string which refers to either the TCPaddress or the local socket to connect to + * @param port the port to use in case of TCP connection, set to 0 if connecting to a local socket + * @param timeout time in ms to allow curl before timing out connection attempts + */ +CURLcode onas_curl_init(CURL **curl, const char *ipaddr, int64_t port, int64_t timeout) +{ + + CURLcode curlcode = CURLE_OK; + + if (!curl || !ipaddr) { + logg("!ClamClient: invalid (NULL) args passed to onas_curl_init\n"); + return CURLE_FAILED_INIT; + } + + /* setup here, but caller needs to cleanup */ + *curl = curl_easy_init(); + + if (!port) { + + /* "ipaddr" is actually our unix socket path here */ + curlcode = curl_easy_setopt(*curl, CURLOPT_UNIX_SOCKET_PATH, ipaddr); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with local unix socket, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + curlcode = curl_easy_setopt(*curl, CURLOPT_URL, "http://localhost/"); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with local address, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + } else { + + curlcode = curl_easy_setopt(*curl, CURLOPT_PORT, port); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with tcp port, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + curlcode = curl_easy_setopt(*curl, CURLOPT_URL, ipaddr); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with tcp address, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + } + + curlcode = curl_easy_setopt(*curl, CURLOPT_NOSIGNAL, 1L); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl to not use signals, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECTTIMEOUT_MS, (long)timeout); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with connect timeout, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + /* we implement our own transfer protocol via send and recv, so we only need to connect */ + curlcode = curl_easy_setopt(*curl, CURLOPT_CONNECT_ONLY, 1L); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl to connect only, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + +#ifdef ONAS_DEBUG + curlcode = curl_easy_setopt(*curl, CURLOPT_VERBOSE, 1L); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not tell curl to be verbose, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } +#endif + + /* don't care about the body of the return message */ + curlcode = curl_easy_setopt(*curl, CURLOPT_NOBODY, 1L); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl to send HEAD request, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + curlcode = curl_easy_setopt(*curl, CURLOPT_HEADER, 0L); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl to not send header, %s\n", curl_easy_strerror(curlcode)); + curl_easy_cleanup(*curl); + return curlcode; + } + + return curlcode; +} + +cl_error_t onas_setup_client(struct onas_context **ctx) +{ + + const struct optstruct *opts; + const struct optstruct *opt; + cl_error_t err; + int remote; + + errno = 0; + + opts = (*ctx)->opts; + + if (optget(opts, "verbose")->enabled) { + mprintf_verbose = 1; + logg_verbose = 1; + } + + if (optget(opts, "infected")->enabled) { + (*ctx)->printinfected = 1; + } + + /* initialize logger */ + + if ((opt = optget(opts, "log"))->enabled) { + logg_file = opt->strarg; + if (logg("--------------------------------------\n")) { + logg("!ClamClient: problem with internal logger\n"); + return CL_EARG; + } + } else { + logg_file = NULL; + } + + if (actsetup(opts)) { + return CL_EARG; + } + + (*ctx)->timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; + (*ctx)->retry_attempts = optget((*ctx)->clamdopts, "OnAccessRetryAttempts")->numarg; + (*ctx)->retry_attempts ? ((*ctx)->retry_on_error = 1) : ((*ctx)->retry_on_error = 0); + optget((*ctx)->clamdopts, "OnAccessDenyOnError")->enabled ? ((*ctx)->deny_on_error = 1) : ((*ctx)->deny_on_error = 0); + + (*ctx)->isremote = onas_check_remote(ctx, &err); + if (err) { + return CL_EARG; + } + + remote = (*ctx)->isremote | optget(opts, "stream")->enabled; +#ifdef HAVE_FD_PASSING + if (!remote && optget((*ctx)->clamdopts, "LocalSocket")->enabled && (optget(opts, "fdpass")->enabled)) { + logg("*ClamClient: client setup to scan via fd passing\n"); + (*ctx)->scantype = FILDES; + (*ctx)->session = optget(opts, "multiscan")->enabled; + } else +#endif + if (remote) { + logg("*ClamClient: client setup to scan via streaming\n"); + (*ctx)->scantype = STREAM; + (*ctx)->session = optget(opts, "multiscan")->enabled; + } else if (optget(opts, "multiscan")->enabled) { + logg("*ClamClient: client setup to scan in multiscan mode\n"); + (*ctx)->scantype = MULTI; + } else if (optget(opts, "allmatch")->enabled) { + logg("*ClamClient: client setup to scan in all-match mode\n"); + (*ctx)->scantype = ALLMATCH; + } else { + logg("*ClamClient: client setup for continuous scanning\n"); + (*ctx)->scantype = CONT; + } + + (*ctx)->maxstream = optget((*ctx)->clamdopts, "StreamMaxLength")->numarg; + + return CL_SUCCESS; +} + +int onas_get_clamd_version(struct onas_context **ctx) +{ + char *buff; + CURL *curl; + CURLcode curlcode; + cl_error_t err = CL_SUCCESS; + int b_remote; + int len, sockd; + struct RCVLN rcv; + int64_t timeout; + + timeout = optget((*ctx)->clamdopts, "OnAccessCurlTimeout")->numarg; + + b_remote = onas_check_remote(ctx, &err); + if (CL_SUCCESS != err) { + logg("!ClamClient: could not check to see if daemon was remote\n"); + return 2; + } + + if (!b_remote) { + curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "LocalSocket")->strarg, 0, timeout); + } else { + curlcode = onas_curl_init(&curl, optget((*ctx)->clamdopts, "TCPAddr")->strarg, (*ctx)->portnum, timeout); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not setup curl with tcp address and port, %s\n", curl_easy_strerror(curlcode)); + /* curl cleanup done in onas_curl_init on error */ + return 2; + } + } + + onas_recvlninit(&rcv, curl); + + curlcode = curl_easy_perform(curl); + if (CURLE_OK != curlcode) { + logg("*ClamClient: could not connect to clam daemon, %s\n", curl_easy_strerror(curlcode)); + return 2; + } + + if (onas_sendln(curl, "zVERSION", 9, timeout)) { + curl_easy_cleanup(curl); + return 2; + } + + while ((len = onas_recvln(&rcv, &buff, NULL, timeout))) { + if (len == -1) { + logg("*ClamClient: clamd did not respond with version information\n"); + break; + } + printf("%s\n", buff); + } + + curl_easy_cleanup(curl); + return 0; +} + +/** + * @brief kick off scanning and return results + * + * @param tcpaddr string string which refers to either the TCPaddress or the local socket to connect to + * @param portnum the port to use in case of TCP connection, set to 0 if connecting to a local socket + * @param scantype the type of scan to perform, e.g. fdpass, stream + * @param maxstream the max streamsize (in bytes) allowed across the socket per file + * @param fname the name of the file to be scanned + * @param fd the file descriptor for the file to be scanned, often (but not always) this is held by fanotify + * @param timeout time in ms to allow curl before timing out connection attempts + * @param sb variable to store and pass all of our stat info on the file so we don't have to access it multiple times (triggering multiple events) + * @param infected return variable indincating whether daemon returned with an infected verdict or not + * @param err return variable passed to the daemon protocol interface indicating how many things went wrong in the course of scanning + * @param ret_code return variable passed to the daemon protocol interface indicating last known issue or success + */ +int onas_client_scan(const char *tcpaddr, int64_t portnum, int32_t scantype, uint64_t maxstream, const char *fname, int fd, int64_t timeout, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) +{ + CURL *curl = NULL; + CURLcode curlcode = CURLE_OK; + int errors = 0; + int sockd, ret; + + *infected = 0; + + if ((sb.st_mode & S_IFMT) != S_IFREG) { + scantype = STREAM; + } + + curlcode = onas_curl_init(&curl, tcpaddr, portnum, timeout); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not init curl for scanning, %s\n", curl_easy_strerror(curlcode)); + /* curl cleanup done in onas_curl_init on error */ + return CL_ECREAT; + } + + curlcode = curl_easy_perform(curl); + if (CURLE_OK != curlcode) { + logg("!ClamClient: could not establish connection, %s\n", curl_easy_strerror(curlcode)); + return CL_ECREAT; + } + + if ((ret = onas_dsresult(curl, scantype, maxstream, fname, fd, timeout, &ret, err, ret_code)) >= 0) { + *infected = ret; + } else { + logg("*ClamClient: connection could not be established ... return code %d\n", *ret_code); + errors = 1; + } + + curl_easy_cleanup(curl); + return *infected ? CL_VIRUS : (errors ? CL_ECREAT : CL_CLEAN); +} diff -Nru clamav-0.101.4+dfsg/clamonacc/client/client.h clamav-0.102.1+dfsg/clamonacc/client/client.h --- clamav-0.101.4+dfsg/clamonacc/client/client.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/client.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Tomasz Kojm, 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. + */ + +#ifndef __ONAS_CLIENT_H +#define __ONAS_CLIENT_H + +#include + +#include "shared/optparser.h" +#include "../clamonacc.h" + +enum { + CONT, + MULTI, + STREAM, + FILDES, + ALLMATCH, + MAX_SCANTYPE = ALLMATCH +}; + +void onas_print_server_version(struct onas_context **ctx); +int onas_client_scan(const char *tcpaddr, int64_t portnum, int32_t scantype, uint64_t maxstream, const char *fname, int fd, int64_t timeout, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); +CURLcode onas_curl_init(CURL **curl, const char *ipaddr, int64_t port, int64_t timeout); +int onas_get_clamd_version(struct onas_context **ctx); +cl_error_t onas_setup_client(struct onas_context **ctx); +int onas_check_remote(struct onas_context **ctx, cl_error_t *err); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/client/communication.c clamav-0.102.1+dfsg/clamonacc/client/communication.c --- clamav-0.101.4+dfsg/clamonacc/client/communication.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/communication.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009-2010 Sourcefire, Inc. + * + * Author: aCaB, Mickey Sola + * + * 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 +#include +#include +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include +#include + +#if !defined(_WIN32) +#include +#endif + +#include "shared/output.h" + +#include "communication.h" + +static int onas_socket_wait(curl_socket_t sockfd, int32_t b_recv, uint64_t timeout_ms); + +/** + * Function from curl example code, Copyright (C) 1998 - 2018, Daniel Stenberg, see COPYING.curl for license details + */ +static int onas_socket_wait(curl_socket_t sockfd, int32_t b_recv, uint64_t timeout_ms) +{ + struct timeval tv; + fd_set infd, outfd, errfd; + int ret; + + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + + FD_ZERO(&infd); + FD_ZERO(&outfd); + FD_ZERO(&errfd); + + FD_SET(sockfd, &errfd); /* always check for error */ + + if (b_recv) { + FD_SET(sockfd, &infd); + } else { + FD_SET(sockfd, &outfd); + } + + /* select() returns the number of signalled sockets or -1 */ + ret = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv); + return ret; +} + +/* Sends bytes over a socket + * Returns 0 on success */ +int onas_sendln(CURL *curl, const void *line, size_t len, int64_t timeout) +{ + size_t sent = 0; + CURLcode curlcode; + curl_socket_t sockfd; + + curlcode = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); + + if (CURLE_OK != curlcode) { + logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(curlcode)); + return 1; + } + + while (len) { + + do { + curlcode = curl_easy_send(curl, line, len, &sent); + if (CURLE_AGAIN == curlcode && !onas_socket_wait(sockfd, 0, timeout)) { + logg("!ClamCom: TIMEOUT while waiting on socket (send)\n"); + return 1; + } + } while (CURLE_AGAIN == curlcode); + + if (sent <= 0) { + if (sent && errno == EINTR) { + continue; + } else { + logg("!Can't send to clamd: %s\n", strerror(errno)); + } + + return 1; + } + + line += sent; + len -= sent; + } + + return 0; +} + +/* Inits a RECVLN struct before it can be used in recvln() - see below */ +void onas_recvlninit(struct RCVLN *rcv_data, CURL *curl) +{ + rcv_data->curl = curl; + rcv_data->curlcode = CURLE_OK; + rcv_data->lnstart = rcv_data->curr = rcv_data->buf; + rcv_data->retlen = 0; +} + +/* Receives a full (terminated with \0) line from a socket + * Sets ret_bol to the begin of the received line, and optionally + * ret_eol to the end of line. + * Should be called repeatedly until all input is consumed + * Returns: + * - the length of the line (a positive number) on success + * - 0 if the connection is closed + * - -1 on error + */ +int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol, int64_t timeout) +{ + char *eol; + int ret = 0; + curl_socket_t sockfd; + + rcv_data->curlcode = curl_easy_getinfo(rcv_data->curl, CURLINFO_ACTIVESOCKET, &sockfd); + + if (CURLE_OK != rcv_data->curlcode) { + logg("!ClamCom: could not get curl active socket info %s\n", curl_easy_strerror(rcv_data->curlcode)); + return -1; + } + + while (1) { + if (!rcv_data->retlen) { + do { + rcv_data->curlcode = curl_easy_recv(rcv_data->curl, rcv_data->curr, + sizeof(rcv_data->buf) - (rcv_data->curr - rcv_data->buf), &(rcv_data->retlen)); + + if (CURLE_AGAIN == rcv_data->curlcode && !onas_socket_wait(sockfd, 1, timeout)) { + logg("!ClamCom: TIMEOUT while waiting on socket (recv)\n"); + return -1; + } + + } while (CURLE_AGAIN == rcv_data->curlcode); + + if (rcv_data->retlen <= 0) { + if (rcv_data->retlen && errno == EINTR) { + rcv_data->retlen = 0; + continue; + } + + if (rcv_data->retlen || rcv_data->curr != rcv_data->buf) { + *rcv_data->curr = '\0'; + + if (strcmp(rcv_data->buf, "UNKNOWN COMMAND\n")) { + logg("!Communication error\n"); + } else { + logg("!Command rejected by clamd (wrong clamd version?)\n"); + } + + return -1; + } + + return 0; + } + } + + if ((eol = memchr(rcv_data->curr, 0, rcv_data->retlen))) { + eol++; + rcv_data->retlen -= eol - rcv_data->curr; + + *ret_bol = rcv_data->lnstart; + if (ret_eol) { + *ret_eol = eol; + } + + ret = eol - rcv_data->lnstart; + if (rcv_data->retlen) { + rcv_data->lnstart = rcv_data->curr = eol; + } else { + rcv_data->lnstart = rcv_data->curr = rcv_data->buf; + } + + return ret; + } + + rcv_data->retlen += rcv_data->curr - rcv_data->lnstart; + + if (!eol && rcv_data->retlen == sizeof(rcv_data->buf)) { + logg("!Overlong reply from clamd\n"); + return -1; + } + + if (!eol) { + if (rcv_data->buf != rcv_data->lnstart) { + memmove(rcv_data->buf, rcv_data->lnstart, rcv_data->retlen); + rcv_data->lnstart = rcv_data->buf; + } + + rcv_data->curr = &rcv_data->lnstart[rcv_data->retlen]; + rcv_data->retlen = 0; + } + } +} diff -Nru clamav-0.101.4+dfsg/clamonacc/client/communication.h clamav-0.102.1+dfsg/clamonacc/client/communication.h --- clamav-0.101.4+dfsg/clamonacc/client/communication.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/communication.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009-2010 Sourcefire, Inc. + * + * Author: aCaB, Mickey Sola + * + * 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. + */ + +#ifndef ONAS_COM_H +#define ONAS_COM_H + +#if HAVE_CONFIG_H +#include "clamav-config.h" +#endif + +#if HAVE_SYS_PARAM_H +#include +#endif + +#include "shared/misc.h" + +struct RCVLN { + char buf[PATH_MAX + 1024]; + CURL *curl; + CURLcode curlcode; + size_t retlen; + char *curr; + char *lnstart; +}; + +int onas_sendln(CURL *curl, const void *line, size_t len, int64_t timeout_ms); +void onas_recvlninit(struct RCVLN *s, CURL *curl); +int onas_recvln(struct RCVLN *rcv_data, char **ret_bol, char **ret_eol, int64_t timeout_ms); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/client/protocol.c clamav-0.102.1+dfsg/clamonacc/client/protocol.c --- clamav-0.101.4+dfsg/clamonacc/client/protocol.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/protocol.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Tomasz Kojm, aCaB, Mickey Sola + * + * 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 + +#if defined(C_SOLARIS) +#ifndef __EXTENSIONS__ +#define __EXTENSIONS__ +#endif +#endif + +/* must be first because it may define _XOPEN_SOURCE */ +#include "shared/fdpassing.h" +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifndef _WIN32 +#include +#include +#include +#include +#endif + +#include "libclamav/clamav.h" +#include "shared/actions.h" +#include "shared/output.h" +#include "shared/misc.h" + +#include "communication.h" +#include "protocol.h" +#include "client.h" + +static const char *scancmd[] = {"CONTSCAN", "MULTISCAN", "INSTREAM", "FILDES", "ALLMATCHSCAN"}; + +/* Issues an INSTREAM command to clamd and streams the given file + * Returns >0 on success, 0 soft fail, -1 hard fail */ +static int onas_send_stream(CURL *curl, const char *filename, int fd, int64_t timeout, uint64_t maxstream) +{ + uint32_t buf[BUFSIZ / sizeof(uint32_t)]; + uint64_t len; + uint64_t todo = maxstream; + int ret = 1; + int close_flag = 0; + + if (0 == fd) { + if (filename) { + if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) < 0) { + logg("~%s: Access denied. ERROR\n", filename); + return 0; + } + //logg("DEBUG: >>>>> fd is %d\n", fd); + close_flag = 1; + } else { + fd = 0; + } + } + + if (onas_sendln(curl, "zINSTREAM", 10, timeout)) { + ret = -1; + goto strm_out; + } + + while ((len = read(fd, &buf[1], sizeof(buf) - sizeof(uint32_t))) > 0) { + if ((uint64_t)len > todo) len = todo; + buf[0] = htonl(len); + if (onas_sendln(curl, (const char *)buf, len + sizeof(uint32_t), timeout)) { + ret = -1; + goto strm_out; + } + todo -= len; + if (!todo) { + len = 0; + break; + } + } + + if (len) { + logg("!Failed to read from %s.\n", filename ? filename : "STDIN"); + ret = 0; + goto strm_out; + } + *buf = 0; + onas_sendln(curl, (const char *)buf, 4, timeout); + +strm_out: + if (close_flag) { + //logg("DEBUG: >>>>> closed fd %d\n", fd); + close(fd); + } + return ret; +} + +#ifdef HAVE_FD_PASSING +/* Issues a FILDES command and pass a FD to clamd + * Returns >0 on success, 0 soft fail, -1 hard fail */ +static int onas_send_fdpass(CURL *curl, const char *filename, int fd, int64_t timeout) +{ + CURLcode result; + struct iovec iov[1]; + struct msghdr msg; + struct cmsghdr *cmsg; + unsigned char fdbuf[CMSG_SPACE(sizeof(int))]; + char dummy[] = ""; + int ret = 1; + int close_flag = 0; + + if (0 == fd) { + if (filename) { + if ((fd = open(filename, O_RDONLY)) < 0) { + logg("~%s: Access denied. ERROR\n", filename); + return 0; + } + close_flag = 1; + } else { + fd = 0; + } + } + if (result = onas_sendln(curl, "zFILDES", 8, timeout)) { + logg("*ClamProto: error sending w/ curl, %s\n", curl_easy_strerror(result)); + ret = -1; + goto fd_out; + } + + iov[0].iov_base = dummy; + iov[0].iov_len = 1; + memset(&msg, 0, sizeof(msg)); + msg.msg_control = fdbuf; + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_controllen = CMSG_LEN(sizeof(int)); + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + if (onas_sendln(curl, &msg, 0, timeout) == -1) { + logg("!FD send failed: %s\n", strerror(errno)); + ret = -1; + goto fd_out; + } +fd_out: + if (close_flag) { + close(fd); + } + return ret; +} +#endif + +/* Sends a proper scan request to clamd and parses its replies + * This is used only in non IDSESSION mode + * Returns the number of infected files or -1 on error + * NOTE: filename may be NULL for STREAM scantype. */ +int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code) +{ + int infected = 0, len = 0, beenthere = 0; + char *bol, *eol; + struct RCVLN rcv; + STATBUF sb; + + onas_recvlninit(&rcv, curl); + + if (ret_code) { + *ret_code = CL_SUCCESS; + } + + switch (scantype) { + case MULTI: + case CONT: + case ALLMATCH: + if (!filename) { + logg("Filename cannot be NULL for MULTISCAN or CONTSCAN.\n"); + if (ret_code) { + *ret_code = CL_ENULLARG; + } + return -1; + } + len = strlen(filename) + strlen(scancmd[scantype]) + 3; + if (!(bol = malloc(len))) { + logg("!Cannot allocate a command buffer: %s\n", strerror(errno)); + if (ret_code) { + *ret_code = CL_EMEM; + } + return -1; + } + sprintf(bol, "z%s %s", scancmd[scantype], filename); + if (onas_sendln(curl, bol, len, timeout)) { + if (ret_code) { + *ret_code = CL_EWRITE; + } + free(bol); + return -1; + } + free(bol); + break; + + case STREAM: + /* NULL filename safe in send_stream() */ + len = onas_send_stream(curl, filename, fd, timeout, maxstream); + break; +#ifdef HAVE_FD_PASSING + case FILDES: + /* NULL filename safe in send_fdpass() */ + len = onas_send_fdpass(curl, filename, fd, timeout); + break; +#endif + } + + if (len <= 0) { + *printok = 0; + if (errors) + (*errors)++; + return len; + } + + while ((len = onas_recvln(&rcv, &bol, &eol, timeout))) { + if (len == -1) { + if (ret_code) { + *ret_code = CL_EREAD; + } + return -1; + } + beenthere = 1; + if (!filename) { + logg("~%s\n", bol); + } + if (len > 7) { + char *colon = strrchr(bol, ':'); + + if (colon && colon[1] != ' ') { + char *br; + *colon = 0; + + br = strrchr(bol, '('); + if (br) { + *br = 0; + } + colon = strrchr(bol, ':'); + } + + if (!colon) { + char *unkco = "UNKNOWN COMMAND"; + if (!strncmp(bol, unkco, sizeof(unkco) - 1)) { + logg("*clamd replied \"UNKNOWN COMMAND\". Command was %s\n", + (scantype < 0 || scantype > MAX_SCANTYPE) ? "unidentified" : scancmd[scantype]); + } else { + logg("*Failed to parse reply: \"%s\"\n", bol); + } + + if (ret_code) { + *ret_code = CL_EPARSE; + } + return -1; + + } else if (!memcmp(eol - 7, " FOUND", 6)) { + static char last_filename[PATH_MAX + 1] = {'\0'}; + *(eol - 7) = 0; + *printok = 0; + + if (scantype != ALLMATCH) { + infected++; + } else { + if (filename != NULL && strcmp(filename, last_filename)) { + infected++; + strncpy(last_filename, filename, PATH_MAX); + last_filename[PATH_MAX] = '\0'; + } + } + + if (filename) { + if (scantype >= STREAM) { + logg("~%s%s FOUND\n", filename, colon); + if (action) { + action(filename); + } + } else { + logg("~%s FOUND\n", bol); + *colon = '\0'; + if (action) { + action(bol); + } + } + } + + if (ret_code) { + *ret_code = CL_VIRUS; + } + + } else if (len > 49 && !memcmp(eol - 50, " lstat() failed: No such file or directory. ERROR", 49)) { + if (errors) { + (*errors)++; + } + *printok = 0; + + if (filename) { + (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); + } + + if (ret_code) { + *ret_code = CL_ESTAT; + } + } else if (len > 41 && !memcmp(eol - 42, " lstat() failed: Permission denied. ERROR", 41)) { + if (errors) { + (*errors)++; + } + *printok = 0; + + if (filename) { + (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); + } + + if (ret_code) { + *ret_code = CL_ESTAT; + } + } else if (len > 21 && !memcmp(eol - 22, " Access denied. ERROR", 21)) { + if (errors) { + (*errors)++; + } + *printok = 0; + + if (filename) { + (scantype >= STREAM) ? logg("*%s%s\n", filename, colon) : logg("*%s\n", bol); + } + + if (ret_code) { + *ret_code = CL_EACCES; + } + } else if (!memcmp(eol - 7, " ERROR", 6)) { + if (errors) { + (*errors)++; + } + *printok = 0; + + if (filename) { + (scantype >= STREAM) ? logg("~%s%s\n", filename, colon) : logg("~%s\n", bol); + } + + if (ret_code) { + *ret_code = CL_ESTATE; + } + } + } + } + if (!beenthere) { + if (!filename) { + logg("STDIN: noreply from clamd\n."); + if (ret_code) { + *ret_code = CL_EACCES; + } + return -1; + } + if (CLAMSTAT(filename, &sb) == -1) { + logg("~%s: stat() failed with %s, clamd may not be responding\n", + filename, strerror(errno)); + if (ret_code) { + *ret_code = CL_EACCES; + } + return -1; + } + if (!S_ISDIR(sb.st_mode)) { + logg("~%s: no reply from clamd\n", filename); + if (ret_code) { + *ret_code = CL_EACCES; + } + return -1; + } + } + return infected; +} diff -Nru clamav-0.101.4+dfsg/clamonacc/client/protocol.h clamav-0.102.1+dfsg/clamonacc/client/protocol.h --- clamav-0.101.4+dfsg/clamonacc/client/protocol.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/client/protocol.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * Copyright (C) 2009 Sourcefire, Inc. + * + * Authors: Tomasz Kojm, aCaB, Mickey Sola + * + * 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. + */ + +#ifndef ONAS_PROTO_H +#define ONAS_PROTO_H + +#include + +#include "shared/misc.h" +#include "../clamonacc.h" + +int onas_dsresult(CURL *curl, int scantype, uint64_t maxstream, const char *filename, int fd, int64_t timeout, int *printok, int *errors, cl_error_t *ret_code); +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/fanotif/fanotif.c clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.c --- clamav-0.101.4+dfsg/clamonacc/fanotif/fanotif.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 + +#if defined(FANOTIFY) + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "libclamav/clamav.h" +#include "libclamav/scanners.h" + +#include "shared/optparser.h" +#include "shared/output.h" + +#include "clamd/server.h" + +#include "../inotif/hash.h" +#include "../inotif/inotif.h" + +#include "../client/client.h" + +#include "../scan/thread.h" +#include "../scan/queue.h" + +#include "../misc/utils.h" + +#include "fanotif.h" + +extern pthread_t ddd_pid; +extern pthread_t scan_queue_pid; +static int onas_fan_fd; + +cl_error_t onas_setup_fanotif(struct onas_context **ctx) +{ + + const struct optstruct *pt; + short int scan; + unsigned int sizelimit = 0, extinfo; + uint64_t fan_mask = FAN_EVENT_ON_CHILD; + + pthread_attr_t ddd_attr; + struct ddd_thrarg *ddd_tharg = NULL; + + ddd_pid = 0; + + if (!ctx || !*ctx) { + logg("!ClamFanotif: unable to start clamonacc. (bad context)\n"); + return CL_EARG; + } + + onas_fan_fd = (*ctx)->fan_fd; + (*ctx)->fan_mask = fan_mask; + + if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && !optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { + logg("*ClamFanotif: kernel-level blocking feature enabled ... preventing malicious files access attempts\n"); + (*ctx)->fan_mask |= FAN_ACCESS_PERM | FAN_OPEN_PERM; + } else { + logg("*ClamFanotif: kernel-level blocking feature disabled ...\n"); + if (optget((*ctx)->clamdopts, "OnAccessPrevention")->enabled && optget((*ctx)->clamdopts, "OnAccessMountPath")->enabled) { + logg("*ClamFanotif: feature not available when watching mounts ... \n"); + } + (*ctx)->fan_mask |= FAN_ACCESS | FAN_OPEN; + } + + if ((pt = optget((*ctx)->clamdopts, "OnAccessMountPath"))->enabled) { + while (pt) { + if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD | FAN_MARK_MOUNT, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { + logg("!ClamFanotif: can't include mountpoint '%s'\n", pt->strarg); + return CL_EARG; + } else { + logg("*ClamFanotif: recursively watching the mount point '%s'\n", pt->strarg); + } + pt = (struct optstruct *)pt->nextarg; + } + + } else if (!optget((*ctx)->clamdopts, "OnAccessDisableDDD")->enabled) { + (*ctx)->ddd_enabled = 1; + } else { + if ((pt = optget((*ctx)->clamdopts, "OnAccessIncludePath"))->enabled) { + while (pt) { + if (fanotify_mark(onas_fan_fd, FAN_MARK_ADD, (*ctx)->fan_mask, (*ctx)->fan_fd, pt->strarg) != 0) { + logg("!ClamFanotif: can't include path '%s'\n", pt->strarg); + return CL_EARG; + } else { + logg("*ClamFanotif: watching directory '%s' (non-recursively)\n", pt->strarg); + } + pt = (struct optstruct *)pt->nextarg; + } + } else { + logg("!ClamFanotif: please specify at least one path with OnAccessIncludePath\n"); + return CL_EARG; + } + } + + /* Load other options. */ + (*ctx)->sizelimit = optget((*ctx)->clamdopts, "OnAccessMaxFileSize")->numarg; + if ((*ctx)->sizelimit) { + logg("*ClamFanotif: max file size limited to %lu bytes\n", (*ctx)->sizelimit); + } else { + logg("*ClamFanotif: file size limit disabled\n"); + } + + extinfo = optget((*ctx)->clamdopts, "ExtendedDetectionInfo")->enabled; + + return CL_SUCCESS; +} + +int onas_fan_eloop(struct onas_context **ctx) +{ + int ret = 0; + int err_cnt = 0; + short int scan; + STATBUF sb; + fd_set rfds; + char buf[4096]; + ssize_t bread; + struct fanotify_event_metadata *fmd; + char fname[1024]; + int len, check, fres; + char err[128]; + + FD_ZERO(&rfds); + FD_SET((*ctx)->fan_fd, &rfds); + + logg("*ClamFanotif: starting fanotify event loop with process id (%d) ... \n", getpid()); + do { + ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); + } while ((ret == -1 && errno == EINTR)); + + time_t start = time(NULL) - 30; + while (((bread = read((*ctx)->fan_fd, buf, sizeof(buf))) > 0) || (errno == EOVERFLOW || errno == EMFILE || errno == EACCES)) { + switch (errno) { + case EOVERFLOW: + if (time(NULL) - start >= 30) { + logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); + logg("*ClamFanotif: file too large for fanotify ... recovering and continuing scans...\n"); + start = time(NULL); + } + + errno = 0; + continue; + case EACCES: + logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); + logg("*ClamFanotif: check your SELinux audit logs and consider adding an exception \ + ... recovering and continuing scans...\n"); + + errno = 0; + continue; + case EMFILE: + logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); + logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n"); + sleep(3); + + errno = 0; + continue; + default: + break; + } + + fmd = (struct fanotify_event_metadata *)buf; + while (FAN_EVENT_OK(fmd, bread)) { + scan = 1; + if (fmd->fd >= 0) { + sprintf(fname, "/proc/self/fd/%d", fmd->fd); + errno = 0; + len = readlink(fname, fname, sizeof(fname) - 1); + if (len == -1) { + close(fmd->fd); + logg("!ClamFanotif: internal error (readlink() failed), %d, %s\n", fmd->fd, strerror(errno)); + if (errno == EBADF) { + logg("ClamWorker: fd already closed ... recovering ...\n"); + continue; + } else { + return 2; + } + } + fname[len] = '\0'; + + if ((check = onas_fan_checkowner(fmd->pid, (*ctx)->clamdopts))) { + scan = 0; + if (check != CHK_SELF) { + logg("*ClamFanotif: %s skipped (excluded UID)\n", fname); + } + } + + if (scan) { + struct onas_scan_event *event_data; + + event_data = cli_calloc(1, sizeof(struct onas_scan_event)); + if (NULL == event_data) { + logg("!ClamFanotif: could not allocate memory for event data struct\n"); + return 2; + } + + /* general mapping */ + onas_map_context_info_to_event_data(*ctx, &event_data); + scan ? event_data->bool_opts |= ONAS_SCTH_B_SCAN : scan; + + /* fanotify specific stuffs */ + event_data->bool_opts |= ONAS_SCTH_B_FANOTIFY; + event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata)); + if (NULL == event_data->fmd) { + logg("!ClamFanotif: could not allocate memory for event data struct fmd\n"); + return 2; + } + memcpy(event_data->fmd, fmd, sizeof(struct fanotify_event_metadata)); + event_data->pathname = cli_strdup(fname); + + logg("*ClamFanotif: attempting to feed consumer queue\n"); + /* feed consumer queue */ + if (CL_SUCCESS != onas_queue_event(event_data)) { + close(fmd->fd); + logg("!ClamFanotif: error occurred while feeding consumer queue ... \n"); + if ((*ctx)->retry_on_error) { + err_cnt++; + if (err_cnt < (*ctx)->retry_attempts) { + logg("ClamFanotif: ... recovering ...\n"); + continue; + } + } + return 2; + } + } else { + if (fmd->mask & FAN_ALL_PERM_EVENTS) { + struct fanotify_response res; + + res.fd = fmd->fd; + res.response = FAN_ALLOW; + + if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) { + logg("!ClamFanotif: error occurred while excluding event\n"); + return 2; + } + } + + if (-1 == close(fmd->fd)) { + logg("!ClamFanotif: error occurred while closing metadata fd, %d\n", fmd->fd); + if (errno == EBADF) { + logg("ClamFanotif: fd already closed ... recovering ...\n"); + } else { + return 2; + } + } + } + } + fmd = FAN_EVENT_NEXT(fmd, bread); + } + do { + ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL); + } while ((ret == -1 && errno == EINTR)); + } + + if (bread < 0) { + logg("!ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno)); + return 2; + } + + return ret; +} +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/fanotif/fanotif.h clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.h --- clamav-0.101.4+dfsg/clamonacc/fanotif/fanotif.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/fanotif/fanotif.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_FAN_H +#define __ONAS_FAN_H + +#include "../clamonacc.h" +#include "libclamav/clamav.h" + +//void *onas_fan_th(void *arg); +cl_error_t onas_setup_fanotif(struct onas_context **ctx); +int onas_fan_eloop(struct onas_context **ctx); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/inotif/hash.c clamav-0.102.1+dfsg/clamonacc/inotif/hash.c --- clamav-0.101.4+dfsg/clamonacc/inotif/hash.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/inotif/hash.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,800 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(FANOTIFY) +#include +#endif + +#include "../fanotif/fanotif.h" + +#include "hash.h" +#include "inotif.h" + +#include "libclamav/clamav.h" +#include "libclamav/scanners.h" +#include "libclamav/str.h" + +#include "shared/optparser.h" +#include "shared/output.h" + +#include "clamd/server.h" +#include "clamd/others.h" +#include "clamd/scanner.h" +#include "../misc/priv_fts.h" + +#if defined(FANOTIFY) + +static struct onas_bucket *onas_bucket_init(); +static void onas_free_bucket(struct onas_bucket *bckt); +static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem); +static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem); + +static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname); + +static struct onas_lnode *onas_listnode_init(void); + +static struct onas_hnode *onas_hashnode_init(void); + +/** + * The data structure described and implemented below is a hash table with elements that also act as relational nodes + * in a tree. This allows for average case constant time retrieval of nodes, and recursive operation on a node and all + * it's children and parents. The memory cost for this speed of relational retrieval is necessarily high, as every node + * must also keep track of it's children in a key-accessible way. To cut down on memory costs, children of nodes are not + * themselves key accessible, but must be combined with their parent in a constant-time operation to be retrieved from + * the table. + * + * Further optimization to retrieval and space management may include storing direct address to given children nodes, but + * such a design will create further complexitiy and time cost at insertion--which must also be as fast as possible in + * order to accomadate the real-time nature of security event processing. + * + * To date, the hashing function itself has not been well studied, and as such buckets were implemented from the start to + * help account for any potential collission issues in its design, as a measure to help offset any major time sinks during + * insertion. + * + * One last important note about this hash table is that to avoid massive slowdowns, it does not grow, but instead relies on + * buckets and a generous default size to distribute that load. Slight hit to retrieval time is a fair cost to pay to avoid + * total loss of service in a real-time system. Future work here might include automatically confiuguring initial hashtable + * size to align with the system being monitored, or max inotify watch points since that's our hard limit anyways. + */ + +static inline uint32_t onas_hshift(uint32_t hash) +{ + + hash = ~hash; + + hash += (hash << 15); + hash ^= (hash >> 12); + hash += (hash << 2); + hash ^= (hash >> 4); + hash += (hash << 3); + hash += (hash << 11); + hash ^= (hash >> 16); + + return hash; +} + +/** + * @brief inline wrapper for onaccess inotify hashing function + * + * @param key the string to be hashed + * @param keylen size of the string + * @param size the size of the hashtable + */ +static inline int onas_hash(const char *key, size_t keylen, uint32_t size) +{ + + uint32_t hash = 1; + uint32_t i; + + for (i = 0; i < keylen; i++) { + hash += key[i]; + hash = onas_hshift(hash); + } + + return hash & (size - 1); +} + +/** + * @brief initialises a bucketed hash table, pre-grown to the given size + */ +int onas_ht_init(struct onas_ht **ht, uint32_t size) +{ + + if (size == 0 || (size & (~size + 1)) != size) return CL_EARG; + + *ht = (struct onas_ht *)cli_malloc(sizeof(struct onas_ht)); + if (!(*ht)) return CL_EMEM; + + **ht = (struct onas_ht){ + .htable = NULL, + .size = size, + .nbckts = 0, + }; + + if (!((*ht)->htable = (struct onas_bucket **)cli_calloc(size, sizeof(struct onas_bucket *)))) { + onas_free_ht(*ht); + return CL_EMEM; + } + + return CL_SUCCESS; +} + +void onas_free_ht(struct onas_ht *ht) +{ + + if (!ht || ht->size == 0) return; + + if (!ht->htable) { + free(ht); + return; + } + + uint32_t i = 0; + for (i = 0; i < ht->size; i++) { + onas_free_bucket(ht->htable[i]); + ht->htable[i] = NULL; + } + + free(ht->htable); + ht->htable = NULL; + + free(ht); + + return; +} + +static struct onas_bucket *onas_bucket_init() +{ + + struct onas_bucket *bckt = (struct onas_bucket *)cli_malloc(sizeof(struct onas_bucket)); + if (!bckt) return NULL; + + *bckt = (struct onas_bucket){ + .size = 0, + .head = NULL, + .tail = NULL}; + + return bckt; +} + +static void onas_free_bucket(struct onas_bucket *bckt) +{ + + if (!bckt) return; + + uint32_t i = 0; + struct onas_element *curr = NULL; + + for (i = 0; i < bckt->size; i++) { + curr = bckt->head; + bckt->head = curr->next; + onas_free_element(curr); + curr = NULL; + } + + free(bckt); + + return; +} +/** + * @brief the hash table uses buckets to store lists of key/value pairings + */ +struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen) +{ + + struct onas_element *elem = (struct onas_element *)cli_malloc(sizeof(struct onas_element)); + if (!elem) return NULL; + + *elem = (struct onas_element){ + .key = key, + .klen = klen, + .data = value, + .next = NULL, + .prev = NULL}; + + return elem; +} + +void onas_free_element(struct onas_element *elem) +{ + + if (!elem) return; + + onas_free_hashnode(elem->data); + + elem->prev = NULL; + elem->next = NULL; + + free(elem); + + return; +} + +int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem) +{ + + if (!ht || !elem || !elem->key) return CL_ENULLARG; + + int idx = onas_hash(elem->key, elem->klen, ht->size); + struct onas_bucket *bckt = ht->htable[idx]; + + int ret = 0; + uint32_t bsize = 0; + + if (bckt == NULL) { + ht->htable[idx] = onas_bucket_init(); + bckt = ht->htable[idx]; + } + + bsize = bckt->size; + ret = onas_bucket_insert(bckt, elem); + + if (ret == CL_SUCCESS) + if (bsize < bckt->size) + ht->nbckts++; + + return ret; +} + +static int onas_bucket_insert(struct onas_bucket *bckt, struct onas_element *elem) +{ + if (!bckt || !elem) return CL_ENULLARG; + + if (bckt->size == 0) { + bckt->head = elem; + bckt->tail = elem; + elem->prev = NULL; + elem->next = NULL; + bckt->size++; + } else { + struct onas_element *btail = bckt->tail; + + btail->next = elem; + elem->prev = btail; + elem->next = NULL; + bckt->tail = elem; + bckt->size++; + } + + return CL_SUCCESS; +} + +/** + * @brief Checks if key exists and optionally stores address to the element corresponding to the key within elem + */ +int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem) +{ + + if (elem) *elem = NULL; + + if (!ht || !key || klen <= 0) return CL_ENULLARG; + + struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)]; + + if (!bckt || bckt->size == 0) return CL_EARG; + + struct onas_element *curr = bckt->head; + + while (curr && strcmp(curr->key, key)) { + curr = curr->next; + } + + if (!curr) return CL_EARG; + + if (elem) *elem = curr; + + return CL_SUCCESS; +} + +/** + * @brief Removes the element corresponding to key from the hashtable and optionally returns a pointer to the removed element. + */ +int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **relem) +{ + if (!ht || !key || klen <= 0) return CL_ENULLARG; + + struct onas_bucket *bckt = ht->htable[onas_hash(key, klen, ht->size)]; + + if (!bckt) return CL_EARG; + + struct onas_element *elem = NULL; + onas_ht_get(ht, key, klen, &elem); + + if (!elem) return CL_EARG; + + int ret = onas_bucket_remove(bckt, elem); + + if (relem) *relem = elem; + + return ret; +} + +static int onas_bucket_remove(struct onas_bucket *bckt, struct onas_element *elem) +{ + if (!bckt || !elem) return CL_ENULLARG; + + struct onas_element *curr = bckt->head; + + while (curr && curr != elem) { + curr = curr->next; + } + + if (!curr) return CL_EARG; + + if (bckt->head == elem) { + bckt->head = elem->next; + if (bckt->head) bckt->head->prev = NULL; + + elem->next = NULL; + } else if (bckt->tail == elem) { + bckt->tail = elem->prev; + if (bckt->tail) bckt->tail->next = NULL; + + elem->prev = NULL; + } else { + struct onas_element *tmp = NULL; + + tmp = elem->prev; + if (tmp) { + tmp->next = elem->next; + tmp = elem->next; + tmp->prev = elem->prev; + } + + elem->prev = NULL; + elem->next = NULL; + } + + bckt->size--; + + return CL_SUCCESS; +} + +/* Dealing with hash nodes and list nodes */ + +/** + * @brief Function to initialize hashnode, which is the data value we're storing in the hash table + */ +static struct onas_hnode *onas_hashnode_init(void) +{ + struct onas_hnode *hnode = NULL; + if (!(hnode = (struct onas_hnode *)cli_malloc(sizeof(struct onas_hnode)))) { + return NULL; + } + + *hnode = (struct onas_hnode){ + .pathlen = 0, + .pathname = NULL, + .prnt_pathlen = 0, + .prnt_pathname = NULL, + .childhead = NULL, + .childtail = NULL, + .wd = 0, + .watched = 0}; + + if (!(hnode->childhead = (struct onas_lnode *)onas_listnode_init())) { + onas_free_hashnode(hnode); + return NULL; + } + + if (!(hnode->childtail = (struct onas_lnode *)onas_listnode_init())) { + onas_free_hashnode(hnode); + return NULL; + } + + hnode->childhead->next = (struct onas_lnode *)hnode->childtail; + hnode->childtail->prev = (struct onas_lnode *)hnode->childhead; + + return hnode; +} + +/** + * @brief Function to initialize listnodes, which ultimately allow us to traverse this datastructure like a tree + */ +static struct onas_lnode *onas_listnode_init(void) +{ + struct onas_lnode *lnode = NULL; + if (!(lnode = (struct onas_lnode *)cli_malloc(sizeof(struct onas_lnode)))) { + return NULL; + } + + *lnode = (struct onas_lnode){ + .dirname = NULL, + .next = NULL, + .prev = NULL}; + + return lnode; +} + +/** + * @brief Function to free hashnodes + */ +void onas_free_hashnode(struct onas_hnode *hnode) +{ + if (!hnode) return; + + onas_free_dirlist(hnode->childhead); + hnode->childhead = NULL; + + free(hnode->pathname); + hnode->pathname = NULL; + + free(hnode->prnt_pathname); + hnode->prnt_pathname = NULL; + + free(hnode); + + return; +} + +/** + * @brief Function to free list of listnode + */ +void onas_free_dirlist(struct onas_lnode *head) +{ + if (!head) return; + struct onas_lnode *curr = head; + struct onas_lnode *tmp = curr; + + while (curr) { + tmp = curr->next; + onas_free_listnode(curr); + curr = tmp; + } + + return; +} + +/** + * @brief Function to free a single listnode + */ +void onas_free_listnode(struct onas_lnode *lnode) +{ + if (!lnode) return; + + lnode->next = NULL; + lnode->prev = NULL; + + free(lnode->dirname); + lnode->dirname = NULL; + + free(lnode); + + return; +} + +/** + * @brief Function to add a single value to a hashnode's listnode + */ +static int onas_add_hashnode_child(struct onas_hnode *node, const char *dirname) +{ + if (!node || !dirname) return CL_ENULLARG; + + struct onas_lnode *child = onas_listnode_init(); + if (!child) return CL_EMEM; + + size_t n = strlen(dirname); + child->dirname = CLI_STRNDUP(dirname, n); + + onas_add_listnode(node->childtail, child); + + return CL_SUCCESS; +} + +/** + * @brief Function to add a dir_listnode to a list + */ +int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node) +{ + if (!tail || !node) return CL_ENULLARG; + + struct onas_lnode *tmp = tail->prev; + + tmp->next = node; + node->prev = tail->prev; + + node->next = tail; + tail->prev = node; + + return CL_SUCCESS; +} + +/** + * @brief Function to remove a listnode based on dirname. + */ +int onas_rm_listnode(struct onas_lnode *head, const char *dirname) +{ + if (!dirname || !head) return CL_ENULLARG; + + struct onas_lnode *curr = head; + size_t n = strlen(dirname); + + while ((curr = curr->next)) { + if (!strncmp(curr->dirname, dirname, n)) { + struct onas_lnode *tmp = curr->prev; + tmp->next = curr->next; + tmp = curr->next; + tmp->prev = curr->prev; + + onas_free_listnode(curr); + + return CL_SUCCESS; + } + } + + return -1; +} + +/*** Dealing with parent/child relationships in the table. ***/ + +/** + * @brief Determines parent of given directory and returns a copy based on full pathname. + */ +inline static char *onas_get_parent(const char *pathname, size_t len) +{ + if (!pathname || len <= 1) return NULL; + + int idx = len - 2; + char *ret = NULL; + + while (idx >= 0 && pathname[idx] != '/') { + idx--; + } + + if (idx == 0) { + idx++; + } + + ret = CLI_STRNDUP(pathname, idx); + if (!ret) { + errno = ENOMEM; + return NULL; + } + + return ret; +} + +/** + * @brief Gets the index at which the name of directory begins from the full pathname. + */ +inline static int onas_get_dirname_idx(const char *pathname, size_t len) +{ + if (!pathname || len <= 1) return -1; + + int idx = len - 2; + + while (idx >= 0 && pathname[idx] != '/') { + idx--; + } + + if (pathname[idx] == '/') + return idx + 1; + + return idx; +} + +/** + * @brief Emancipates the specified child from the specified parent directory, typical done after a delete or move event + * + * @param ht the hashtable structure + * @param prntpath the full path of the parent director to be used hashed and used as a key to retrieve the corresponding entry from the table + * @param prntlen the length of the parent path in bytes + * @param childpath the path of the child to be deassociated with the passed parent + * @param childlen the length of the child path in bytes + */ +int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen) +{ + + if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG; + + struct onas_element *elem = NULL; + struct onas_hnode *hnode = NULL; + int idx = onas_get_dirname_idx(childpath, childlen); + int ret = 0; + + if (idx <= 0) return CL_SUCCESS; + + if (onas_ht_get(ht, prntpath, prntlen, &elem) != CL_SUCCESS) return CL_EARG; + + hnode = elem->data; + + if ((ret = onas_rm_listnode(hnode->childhead, &(childpath[idx])))) return CL_EARG; + + return CL_SUCCESS; +} + +/** + * @brief The specified parent adds the specified child to its list, typical done after a create, or move event + * + * @param ht the hashtable structure + * @param prntpath the full path of the parent director to be used hashed and used as a key to retrieve the corresponding entry from the table + * @param prntlen the length of the parent path in bytes + * @param childpath the path of the child to be associated with the passed parent + * @param childlen the length of the child path in bytes + */ +int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen) +{ + if (!ht || !prntpath || prntlen <= 0 || !childpath || childlen <= 1) return CL_ENULLARG; + + struct onas_element *elem = NULL; + struct onas_hnode *hnode = NULL; + int idx = onas_get_dirname_idx(childpath, childlen); + + if (idx <= 0) return CL_SUCCESS; + + if (onas_ht_get(ht, prntpath, prntlen, &elem)) return CL_EARG; + hnode = elem->data; + + return onas_add_hashnode_child(hnode, &(childpath[idx])); +} + +/*** Dealing with hierarchy changes. ***/ + +/** + * @brief Adds the hierarchy under pathname to the tree and allocates all necessary memory. + */ +int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname) +{ + if (!ht || !pathname) return CL_ENULLARG; + + int ret = 0; + FTS *ftsp = NULL; + int ftspopts = FTS_PHYSICAL | FTS_XDEV; + FTSENT *curr = NULL; + FTSENT *childlist = NULL; + + size_t len = strlen(pathname); + char *prnt = onas_get_parent(pathname, len); + if (prnt) onas_ht_add_child(ht, prnt, strlen(prnt), pathname, len); + free(prnt); + + char *const pathargv[] = {(char *)pathname, NULL}; + if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { + logg("!ClamHash: could not open '%s'\n", pathname); + ret = CL_EARG; + goto out; + } + + while ((curr = _priv_fts_read(ftsp))) { + + struct onas_hnode *hnode = NULL; + + /* May want to handle other options in the future. */ + switch (curr->fts_info) { + case FTS_D: + hnode = onas_hashnode_init(); + if (!hnode) { + ret = CL_EMEM; + goto out; + } + + hnode->pathlen = curr->fts_pathlen; + hnode->pathname = CLI_STRNDUP(curr->fts_path, hnode->pathlen); + + hnode->prnt_pathname = onas_get_parent(hnode->pathname, hnode->pathlen); + if (hnode->prnt_pathname) + hnode->prnt_pathlen = strlen(hnode->prnt_pathname); + else + hnode->prnt_pathlen = 0; + break; + default: + continue; + } + + if ((childlist = _priv_fts_children(ftsp, 0))) { + do { + if (childlist->fts_info == FTS_D) { + if (CL_EMEM == onas_add_hashnode_child(hnode, childlist->fts_name)) { + + ret = CL_EMEM; + goto out; + } + } + } while ((childlist = childlist->fts_link)); + } + + struct onas_element *elem = onas_element_init(hnode, hnode->pathname, hnode->pathlen); + if (!elem) { + ret = CL_EMEM; + goto out; + } + + if (onas_ht_insert(ht, elem)) { + + ret = -1; + goto out; + } + } + +out: + if (ftsp) { + _priv_fts_close(ftsp); + } + + if (ret) { + return ret; + } + + return CL_SUCCESS; +} + +/** + * @brief Removes the underlying hierarchy from the tree and frees all associated memory. + */ +int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level) +{ + if (!ht || !pathname || len <= 0) return CL_ENULLARG; + + struct onas_hnode *hnode = NULL; + struct onas_element *elem = NULL; + char *prntname = NULL; + size_t prntlen = 0; + + if (onas_ht_get(ht, pathname, len, &elem)) return CL_EARG; + + hnode = elem->data; + + struct onas_lnode *curr = hnode->childhead; + + if (level == 0) { + if (!(prntname = onas_get_parent(pathname, len))) return CL_EARG; + + prntlen = strlen(prntname); + if (onas_ht_rm_child(ht, prntname, prntlen, pathname, len)) return CL_EARG; + + free(prntname); + } + + while (curr->next != hnode->childtail) { + curr = curr->next; + + size_t size = len + strlen(curr->dirname) + 2; + char *child_path = (char *)cli_malloc(size); + if (child_path == NULL) + return CL_EMEM; + if (hnode->pathname[len - 1] == '/') + snprintf(child_path, size, "%s%s", hnode->pathname, curr->dirname); + else + snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); + onas_ht_rm_hierarchy(ht, child_path, size, level + 1); + free(child_path); + } + + onas_ht_remove(ht, pathname, len, NULL); + onas_free_element(elem); + + return CL_SUCCESS; +} +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/inotif/hash.h clamav-0.102.1+dfsg/clamonacc/inotif/hash.h --- clamav-0.101.4+dfsg/clamonacc/inotif/hash.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/inotif/hash.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_HASH_H +#define __ONAS_HASH_H + +#if defined(FANOTIFY) + +#define ONAS_FANWATCH 0x1 +#define ONAS_INWATCH 0x2 +#define ONAS_STOPWATCH 0x3 + +#define ONAS_DEFAULT_HT_SIZE 1 << 18 + +struct onas_element { + + const char *key; + size_t klen; + struct onas_hnode *data; + + struct onas_element *next; + struct onas_element *prev; +}; + +struct onas_bucket { + + uint32_t size; + + struct onas_element *head; + struct onas_element *tail; +}; + +struct onas_ht { + + struct onas_bucket **htable; + + /* Must be a sufficiently high power of two--will not grow. */ + uint32_t size; + uint32_t nbckts; +}; + +/* Directory node struct for lists */ +struct onas_lnode { + + /* List stuffs */ + char *dirname; + struct onas_lnode *next; + struct onas_lnode *prev; +}; + +/* Directory node struct for hash tables */ +struct onas_hnode { + + /* Path info */ + int pathlen; + char *pathname; + + /* Parent info */ + int prnt_pathlen; + char *prnt_pathname; + + /* Child head and tail are empty sentinels */ + struct onas_lnode *childhead; + struct onas_lnode *childtail; + + /* Inotify watch descriptor */ + int wd; + + /* Watched stuffs */ + uint32_t watched; +}; + +void onas_free_ht(struct onas_ht *ht); +int onas_ht_init(struct onas_ht **ht, uint32_t table_size); +int onas_ht_insert(struct onas_ht *ht, struct onas_element *elem); +int onas_ht_remove(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem); +int onas_ht_get(struct onas_ht *ht, const char *key, size_t klen, struct onas_element **elem); +int onas_ht_rm_hierarchy(struct onas_ht *ht, const char *pathname, size_t len, int level); +int onas_ht_add_hierarchy(struct onas_ht *ht, const char *pathname); +int onas_ht_add_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen); +int onas_ht_rm_child(struct onas_ht *ht, const char *prntpath, size_t prntlen, const char *childpath, size_t childlen); + +void onas_free_element(struct onas_element *elem); +struct onas_element *onas_element_init(struct onas_hnode *value, const char *key, size_t klen); + +void onas_free_hashnode(struct onas_hnode *hnode); + +void onas_free_listnode(struct onas_lnode *lnode); +int onas_add_listnode(struct onas_lnode *tail, struct onas_lnode *node); +int onas_rm_listnode(struct onas_lnode *head, const char *dirname); + +void onas_free_dirlist(struct onas_lnode *head); + +#endif +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/inotif/inotif.c clamav-0.102.1+dfsg/clamonacc/inotif/inotif.c --- clamav-0.101.4+dfsg/clamonacc/inotif/inotif.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/inotif/inotif.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,773 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(FANOTIFY) +#include +#include +#endif + +#include "../fanotif/fanotif.h" + +#include "hash.h" +#include "inotif.h" + +#include "../scan/thread.h" +#include "../scan/queue.h" +#include "../misc/utils.h" + +#include "libclamav/clamav.h" +#include "libclamav/scanners.h" + +#include "shared/optparser.h" +#include "shared/output.h" + +#include "clamd/server.h" +#include "clamd/others.h" +#include "clamd/scanner.h" + +#if defined(FANOTIFY) + +static int onas_ddd_init_ht(uint32_t ht_size); +static int onas_ddd_init_wdlt(uint64_t nwatches); +static int onas_ddd_grow_wdlt(); + +static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask); +static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type); +static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd); +static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type); + +static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask); +static void onas_ddd_handle_in_create(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask); +static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); +static void onas_ddd_handle_in_delete(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd); +static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options); +static void onas_ddd_exit(void *arg); + +/* TODO: Unglobalize these. */ +static struct onas_ht *ddd_ht; +static char **wdlt; +static uint32_t wdlt_len; +static int onas_in_fd; +extern pthread_t ddd_pid; + +static int onas_ddd_init_ht(uint32_t ht_size) +{ + + if (ht_size <= 0) + ht_size = ONAS_DEFAULT_HT_SIZE; + + return onas_ht_init(&ddd_ht, ht_size); +} + +/** + * @brief Initialize watch descriptor lookup table which we use alongside inotify to keep track of which open watchpoints correspond to which objects + */ +static int onas_ddd_init_wdlt(uint64_t nwatches) +{ + + if (nwatches <= 0) return CL_EARG; + + wdlt = (char **)cli_calloc(nwatches << 1, sizeof(char *)); + if (!wdlt) return CL_EMEM; + + wdlt_len = nwatches << 1; + + return CL_SUCCESS; +} + +/** + * @brief Initialize watch descriptor lookup table which we use alongside inotify to keep track of which open watchpoints correspond to which objects + */ +static int onas_ddd_grow_wdlt() +{ + + char **ptr = NULL; + + ptr = (char **)cli_realloc(wdlt, wdlt_len << 1); + if (ptr) { + wdlt = ptr; + memset(&ptr[wdlt_len], 0, sizeof(char *) * (wdlt_len - 1)); + } else { + return CL_EMEM; + } + + wdlt_len <<= 1; + + return CL_SUCCESS; +} + +/* TODO: Support configuration for changing/setting number of inotify watches. */ +int onas_ddd_init(uint64_t nwatches, size_t ht_size) +{ + + const char *nwatch_file = "/proc/sys/fs/inotify/max_user_watches"; + int nwfd = 0; + int ret = 0; + char nwatch_str[MAX_WATCH_LEN]; + char *p = NULL; + nwatches = 0; + + nwfd = open(nwatch_file, O_RDONLY); + if (nwfd < 0) return CL_EOPEN; + + ret = read(nwfd, nwatch_str, MAX_WATCH_LEN); + close(nwfd); + if (ret < 0) return CL_EREAD; + + nwatches = strtol(nwatch_str, &p, 10); + + ret = onas_ddd_init_wdlt(nwatches); + if (ret) return ret; + + ret = onas_ddd_init_ht(ht_size); + if (ret) return ret; + + return CL_SUCCESS; +} + +/** + * @brief convenience function for adding both inotify and fanotify watchpoints for a single path in one go + */ +static int onas_ddd_watch(const char *pathname, int fan_fd, uint64_t fan_mask, int in_fd, uint64_t in_mask) +{ + if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG; + + int ret = CL_SUCCESS; + size_t len = strlen(pathname); + + ret = onas_ddd_watch_hierarchy(pathname, len, in_fd, in_mask, ONAS_IN); + if (ret) return ret; + + ret = onas_ddd_watch_hierarchy(pathname, len, fan_fd, fan_mask, ONAS_FAN); + if (ret) return ret; + + return CL_SUCCESS; +} + +/** + * @brief recursively adds a hierarchy from the hash table and all watches of a single type to specified object + * + * @param pathname the directory to start watching + * @param len the size of pathname in bytes + * @param fd the fanotify or inotify file descriptor + * @param mask options for watching the path + * @param type specifies whether or not to add inotify or fanotify watchpoints and the type of fd passed + */ +static int onas_ddd_watch_hierarchy(const char *pathname, size_t len, int fd, uint64_t mask, uint32_t type) +{ + + if (!pathname || fd <= 0 || !type) return CL_ENULLARG; + + if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG; + + struct onas_hnode *hnode = NULL; + struct onas_element *elem = NULL; + int wd = 0; + + if (onas_ht_get(ddd_ht, pathname, len, &elem) != CL_SUCCESS) return CL_EARG; + + hnode = elem->data; + + if (type & ONAS_IN) { + wd = inotify_add_watch(fd, pathname, (uint32_t)mask); + + if (wd < 0) return CL_EARG; + + if ((uint32_t)wd >= wdlt_len) { + onas_ddd_grow_wdlt(); + } + + /* Link the hash node to the watch descriptor lookup table */ + hnode->wd = wd; + wdlt[wd] = hnode->pathname; + + hnode->watched |= ONAS_INWATCH; + } else if (type & ONAS_FAN) { + if (fanotify_mark(fd, FAN_MARK_ADD, mask, AT_FDCWD, hnode->pathname) < 0) return CL_EARG; + hnode->watched |= ONAS_FANWATCH; + } else { + return CL_EARG; + } + + /* recursively watch all children */ + struct onas_lnode *curr = hnode->childhead; + + while (curr->next != hnode->childtail) { + curr = curr->next; + + size_t size = len + strlen(curr->dirname) + 2; + char *child_path = (char *)cli_malloc(size); + if (child_path == NULL) + return CL_EMEM; + if (hnode->pathname[len - 1] == '/') + snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname); + else + snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); + + if (onas_ddd_watch_hierarchy(child_path, strlen(child_path), fd, mask, type)) { + return CL_EARG; + } + free(child_path); + } + + return CL_SUCCESS; +} + +/** + * @brief convenience function for removing both inotify and fanotify watchpoints for a single path in one go + */ +static int onas_ddd_unwatch(const char *pathname, int fan_fd, int in_fd) +{ + if (!pathname || fan_fd <= 0 || in_fd <= 0) return CL_ENULLARG; + + int ret = CL_SUCCESS; + size_t len = strlen(pathname); + + ret = onas_ddd_unwatch_hierarchy(pathname, len, in_fd, ONAS_IN); + if (ret) return ret; + + ret = onas_ddd_unwatch_hierarchy(pathname, len, fan_fd, ONAS_FAN); + if (ret) return ret; + + return CL_SUCCESS; +} + +/** + * @brief recursively removes a hierarchy from the hash table and drops all watches of a single type from linked objects + * + * @param pathname the directory to stop watching + * @param len the size of pathname in bytes + * @param fd the fanotify or inotify file descriptor + * @param type specifies whether or not to remove inotify or fanotify watchpoints and the type of fd passed + */ +static int onas_ddd_unwatch_hierarchy(const char *pathname, size_t len, int fd, uint32_t type) +{ + + if (!pathname || fd <= 0 || !type) return CL_ENULLARG; + + if (type == (ONAS_IN | ONAS_FAN)) return CL_EARG; + + struct onas_hnode *hnode = NULL; + struct onas_element *elem = NULL; + int wd = 0; + + if (onas_ht_get(ddd_ht, pathname, len, &elem)) return CL_EARG; + + hnode = elem->data; + + if (type & ONAS_IN) { + wd = hnode->wd; + + if (!inotify_rm_watch(fd, wd)) return CL_EARG; + + /* Unlink the hash node from the watch descriptor lookup table */ + hnode->wd = 0; + wdlt[wd] = NULL; + + hnode->watched = ONAS_STOPWATCH; + } else if (type & ONAS_FAN) { + if (fanotify_mark(fd, FAN_MARK_REMOVE, 0, AT_FDCWD, hnode->pathname) < 0) return CL_EARG; + hnode->watched = ONAS_STOPWATCH; + } else { + return CL_EARG; + } + + /* free all children recursively */ + struct onas_lnode *curr = hnode->childhead; + + while (curr->next != hnode->childtail) { + curr = curr->next; + + size_t size = len + strlen(curr->dirname) + 2; + char *child_path = (char *)cli_malloc(size); + if (child_path == NULL) + return CL_EMEM; + if (hnode->pathname[len - 1] == '/') + snprintf(child_path, --size, "%s%s", hnode->pathname, curr->dirname); + else + snprintf(child_path, size, "%s/%s", hnode->pathname, curr->dirname); + + onas_ddd_unwatch_hierarchy(child_path, strlen(child_path), fd, type); + free(child_path); + } + + return CL_SUCCESS; +} + +cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx) +{ + + pthread_attr_t ddd_attr; + int32_t thread_started = 1; + + if (!ctx || !*ctx) { + logg("!ClamInotif: unable to start clamonacc. (bad context)\n"); + return CL_EARG; + } + + if ((*ctx)->ddd_enabled) { + do { + if (pthread_attr_init(&ddd_attr)) break; + pthread_attr_setdetachstate(&ddd_attr, PTHREAD_CREATE_JOINABLE); + thread_started = pthread_create(&ddd_pid, &ddd_attr, onas_ddd_th, *ctx); + } while (0); + } + + if (0 != thread_started) { + /* Failed to create thread */ + logg("!ClamInotif: Unable to start dynamic directory determination ... \n"); + return CL_ECREAT; + } + + return CL_SUCCESS; +} + +void *onas_ddd_th(void *arg) +{ + struct onas_context *ctx = (struct onas_context *)arg; + sigset_t sigset; + struct sigaction act; + const struct optstruct *pt; + uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE; + fd_set rfds; + char buf[4096]; + ssize_t bread; + const struct inotify_event *event; + int ret, len, idx; + + char **include_list = NULL; + char **exclude_list = NULL; + int num_exdirs, num_indirs; + cl_error_t err; + + /* ignore all signals */ + sigfillset(&sigset); + sigdelset(&sigset, SIGUSR1); + sigdelset(&sigset, SIGUSR2); + /* The behavior of a process is undefined after it ignores a + * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ + sigdelset(&sigset, SIGFPE); + sigdelset(&sigset, SIGILL); + sigdelset(&sigset, SIGTERM); + sigdelset(&sigset, SIGINT); +#ifdef SIGBUS + sigdelset(&sigset, SIGBUS); +#endif + + logg("*ClamInotif: starting inotify event loop ...\n"); + + onas_in_fd = inotify_init1(IN_NONBLOCK); + if (onas_in_fd == -1) { + logg("!ClamInotif: could not init inotify\n"); + return NULL; + } + + ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE); + if (ret) { + logg("!ClamInotif: failed to initialize DDD system\n"); + return NULL; + } + + logg("*ClamInotif: dynamically determining directory hierarchy...\n"); + /* Add provided paths recursively. */ + + if (!optget(ctx->opts, "watch-list")->enabled && !optget(ctx->clamdopts, "OnAccessIncludePath")->enabled) { + logg("!ClamInotif: Please specify at least one path with OnAccessIncludePath\n"); + return NULL; + } + + if ((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { + + while (pt) { + if (!strcmp(pt->strarg, "/")) { + logg("!ClamInotif: not including path '%s' while DDD is enabled\n", pt->strarg); + logg("!ClamInotif: please use the OnAccessMountPath option to watch '%s'\n", pt->strarg); + pt = (struct optstruct *)pt->nextarg; + continue; + } + if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) { + if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) { + logg("!ClamInotif: can't include '%s'\n", pt->strarg); + return NULL; + } else { + logg("ClamInotif: watching '%s' (and all sub-directories)\n", pt->strarg); + } + } + + pt = (struct optstruct *)pt->nextarg; + } + } + + if ((pt = optget(ctx->opts, "watch-list"))->enabled) { + + num_indirs = 0; + err = CL_SUCCESS; + + include_list = onas_get_opt_list(pt->strarg, &num_indirs, &err); + if (NULL == include_list) { + logg("!ClamInotif: could not parse include list (%d)\n", err); + return NULL; + } + + idx = 0; + while (NULL != include_list[idx]) { + if (onas_ht_get(ddd_ht, include_list[idx], strlen(include_list[idx]), NULL) != CL_SUCCESS) { + if (onas_ht_add_hierarchy(ddd_ht, include_list[idx])) { + logg("!ClamInotif: can't include '%s'\n", include_list[idx]); + return NULL; + } else { + logg("ClamInotif: watching '%s' (and all sub-directories)\n", include_list[idx]); + } + } + + idx++; + } + } + + /* Remove provided paths recursively. */ + if ((pt = optget(ctx->clamdopts, "OnAccessExcludePath"))->enabled) { + while (pt) { + size_t ptlen = strlen(pt->strarg); + if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { + if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) { + logg("!ClamInotif: can't exclude '%s'\n", pt->strarg); + return NULL; + } else + logg("ClamInotif: excluding '%s' (and all sub-directories)\n", pt->strarg); + } + + pt = (struct optstruct *)pt->nextarg; + } + } + + if ((pt = optget(ctx->opts, "exclude-list"))->enabled) { + + num_exdirs = 0; + err = CL_SUCCESS; + + exclude_list = onas_get_opt_list(pt->strarg, &num_exdirs, &err); + if (NULL == exclude_list) { + logg("!ClamInotif: could not parse exclude list (%d)\n", err); + return NULL; + } + + idx = 0; + while (exclude_list[idx] != NULL) { + if (onas_ht_get(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), NULL) == CL_SUCCESS) { + if (onas_ht_rm_hierarchy(ddd_ht, exclude_list[idx], strlen(exclude_list[idx]), 0)) { + logg("!ClamInotif: can't exclude '%s'\n", exclude_list[idx]); + return NULL; + } else { + logg("ClamInotif: excluding '%s' (and all sub-directories)\n", exclude_list[idx]); + } + } + + idx++; + } + } + + /* Watch provided paths recursively */ + if ((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) { + while (pt) { + errno = 0; + size_t ptlen = strlen(pt->strarg); + if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) { + if (err = onas_ddd_watch(pt->strarg, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { + + if (0 == errno) { + logg("!ClamInotif: could not watch path '%s', %d\n ", pt->strarg, err); + } else { + logg("!ClamInotif: could not watch path '%s', %s\n", pt->strarg, strerror(errno)); + if (errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { + logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); + + kill(getpid(), SIGTERM); + } + if (errno == ENOSPC) { + + logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); + logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); + + kill(getpid(), SIGTERM); + } + } + } + pt = (struct optstruct *)pt->nextarg; + } + } + } + + if (NULL != include_list) { + idx = 0; + while (NULL != include_list[idx]) { + errno = 0; + uint64_t ptlen = strlen(include_list[idx]); + if (onas_ht_get(ddd_ht, include_list[idx], ptlen, NULL) == CL_SUCCESS) { + if (err = onas_ddd_watch(include_list[idx], ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) { + if (0 == errno) { + logg("!ClamInotif: could not watch path '%s', %d\n ", include_list[idx], err); + } else { + logg("!ClamInotif: could not watch path '%s', %s\n", include_list[idx], strerror(errno)); + if (errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) { + logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n"); + + kill(getpid(), SIGTERM); + } + if (errno == ENOSPC) { + + logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n"); + logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n"); + + kill(getpid(), SIGTERM); + } + } + } + } + idx++; + } + } + + if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { + logg("ClamInotif: extra scanning on inotify events enabled\n"); + } + + FD_ZERO(&rfds); + FD_SET(onas_in_fd, &rfds); + + pthread_cleanup_push(onas_ddd_exit, NULL); + + while (1) { + do { + ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL); + } while (ret == -1 && errno == EINTR); + + while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) { + pthread_testcancel(); + /* Handle events. */ + int wd; + char *p = buf; + const char *path = NULL; + const char *child = NULL; + for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) { + + event = (const struct inotify_event *)p; + wd = event->wd; + path = wdlt[wd]; + child = event->name; + + if (path == NULL) { + logg("*ClamInotif: watch descriptor not found in lookup table ... skipping\n"); + continue; + } + + len = strlen(path); + size_t size = strlen(child) + len + 2; + char *child_path = (char *)cli_malloc(size); + if (child_path == NULL) { + logg("*ClamInotif: could not allocate space for child path ... aborting\n"); + return NULL; + } + + if (path[len - 1] == '/') { + snprintf(child_path, --size, "%s%s", path, child); + } else { + snprintf(child_path, size, "%s/%s", path, child); + } + + if (event->mask & IN_DELETE) { + onas_ddd_handle_in_delete(ctx, path, child_path, event, wd); + + } else if (event->mask & IN_MOVED_FROM) { + onas_ddd_handle_in_moved_from(ctx, path, child_path, event, wd); + + } else if (event->mask & IN_CREATE) { + onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask); + + } else if (event->mask & IN_MOVED_TO) { + onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask); + } + + free(child_path); + child_path = NULL; + } + } + } + + logg("*ClamInotif: exiting inotify event thread\n"); + pthread_cleanup_pop(1); + return NULL; +} + +static void onas_ddd_handle_in_delete(struct onas_context *ctx, + const char *path, const char *child_path, const struct inotify_event *event, int wd) +{ + + struct stat s; + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; + if (!(event->mask & IN_ISDIR)) return; + + logg("*ClamInotif: DELETE - removing %s from %s with wd:%d\n", child_path, path, wd); + onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); + onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); + + return; +} + +static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, + const char *path, const char *child_path, const struct inotify_event *event, int wd) +{ + + struct stat s; + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; + if (!(event->mask & IN_ISDIR)) return; + + logg("*ClamInotif: MOVED_FROM - removing %s from %s with wd:%d\n", child_path, path, wd); + onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd); + onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0); + + return; +} + +static void onas_ddd_handle_in_create(struct onas_context *ctx, + const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) +{ + + struct stat s; + + if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { + onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); + + } else if (event->mask & IN_ISDIR) { + logg("*ClamInotif: CREATE - adding %s to %s with wd:%d\n", child_path, path, wd); + onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); + + onas_ht_add_hierarchy(ddd_ht, child_path); + onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); + } + } else { + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; + if (!(event->mask & IN_ISDIR)) return; + + logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); + onas_ht_add_hierarchy(ddd_ht, child_path); + onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); + } + + return; +} + +static void onas_ddd_handle_in_moved_to(struct onas_context *ctx, + const char *path, const char *child_path, const struct inotify_event *event, int wd, uint64_t in_mask) +{ + + struct stat s; + if (optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) { + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) { + onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_FILE); + + } else if (event->mask & IN_ISDIR) { + logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); + onas_ddd_handle_extra_scanning(ctx, child_path, ONAS_SCTH_B_DIR); + + onas_ht_add_hierarchy(ddd_ht, child_path); + onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); + } + } else { + if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return; + if (!(event->mask & IN_ISDIR)) return; + + logg("*ClamInotif: MOVED_TO - adding %s to %s with wd:%d\n", child_path, path, wd); + onas_ht_add_hierarchy(ddd_ht, child_path); + onas_ddd_watch(child_path, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask); + } + + return; +} + +static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options) +{ + + struct onas_scan_event *event_data; + + event_data = (struct onas_scan_event *)cli_calloc(1, sizeof(struct onas_scan_event)); + if (NULL == event_data) { + logg("!ClamInotif: could not allocate memory for event data struct\n"); + } + + /* general mapping */ + onas_map_context_info_to_event_data(ctx, &event_data); + event_data->pathname = cli_strdup(pathname); + event_data->bool_opts |= ONAS_SCTH_B_SCAN; + + /* inotify specific stuffs */ + event_data->bool_opts |= ONAS_SCTH_B_INOTIFY; + extra_options &ONAS_SCTH_B_FILE ? event_data->bool_opts |= ONAS_SCTH_B_FILE : extra_options; + extra_options &ONAS_SCTH_B_DIR ? event_data->bool_opts |= ONAS_SCTH_B_DIR : extra_options; + + logg("*ClamInotif: attempting to feed consumer queue\n"); + /* feed consumer queue */ + if (CL_SUCCESS != onas_queue_event(event_data)) { + logg("!ClamInotif: error occurred while feeding consumer queue extra event ... continuing ...\n"); + return; + } + + return; +} + +static void onas_ddd_exit(void *arg) +{ + logg("*ClamInotif: onas_ddd_exit()\n"); + + if (onas_in_fd) { + close(onas_in_fd); + } + onas_in_fd = 0; + + if (ddd_ht) { + onas_free_ht(ddd_ht); + } + ddd_ht = NULL; + + if (wdlt) { + free(wdlt); + } + wdlt = NULL; + + logg("ClamInotif: stopped\n"); +} + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/inotif/inotif.h clamav-0.102.1+dfsg/clamonacc/inotif/inotif.h --- clamav-0.101.4+dfsg/clamonacc/inotif/inotif.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/inotif/inotif.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_IN_H +#define __ONAS_IN_H + +#if defined(FANOTIFY) + +#include "shared/optparser.h" +#include "libclamav/clamav.h" + +/* + * Extra options for onas_scan_th(). + */ +#define ONAS_IN 0x01 +#define ONAS_FAN 0x02 + +#define MAX_WATCH_LEN 7 + +struct ddd_thrarg { + int sid; + struct cl_scan_options *options; + int fan_fd; + uint64_t fan_mask; + const struct optstruct *opts; + const struct cl_engine *engine; +}; + +int onas_ddd_init(uint64_t nwatches, size_t ht_size); +void *onas_ddd_th(void *arg); +int onas_ddd_init(uint64_t nwatches, size_t ht_size); +cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx); + +#endif +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/misc/fts.c clamav-0.102.1+dfsg/clamonacc/misc/fts.c --- clamav-0.101.4+dfsg/clamonacc/misc/fts.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/misc/fts.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,1165 @@ +/* File tree traversal functions. + Copyright (C) 1994-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#if HAVE_CONFIG_H +#include "clamav-config.h" +#endif + +#include +#include +#include +#include +#include +#include "priv_fts.h" +#include +#include +#include + +#define FTS_OPEN _priv_fts_open +#define FTS_CLOSE _priv_fts_close +#define FTS_READ _priv_fts_read +#define FTS_SET _priv_fts_set +#define FTS_CHILDREN _priv_fts_children +#define FTSOBJ FTS +#define FTSENTRY FTSENT +#define INO_T ino_t +#define STAT stat +#define LSTAT lstat + +#define internal_function +#define __set_errno(val) (errno = (val)) + +/* Largest alignment size needed, minus one. + Usually long double is the worst case. */ +#ifndef ALIGNBYTES +#define ALIGNBYTES (__alignof__(long double) - 1) +#endif +/* Align P to that size. */ +#ifndef ALIGN +#define ALIGN(p) (((unsigned long int)(p) + ALIGNBYTES) & ~ALIGNBYTES) +#endif + +/* Support for the LFS API version. */ +#ifndef FTS_OPEN +#define FTS_OPEN fts_open +#define FTS_CLOSE fts_close +#define FTS_READ fts_read +#define FTS_SET fts_set +#define FTS_CHILDREN fts_children +#define FTSOBJ FTS +#define FTSENTRY FTSENT +#define INO_T ino_t +#define STAT stat +#define LSTAT lstat +#endif + +static FTSENTRY *fts_alloc(FTSOBJ *, const char *, size_t) internal_function; +static FTSENTRY *fts_build(FTSOBJ *, int) internal_function; +static void fts_lfree(FTSENTRY *) internal_function; +static void fts_load(FTSOBJ *, FTSENTRY *) internal_function; +static size_t fts_maxarglen(char *const *) internal_function; +static void fts_padjust(FTSOBJ *, FTSENTRY *) internal_function; +static int fts_palloc(FTSOBJ *, size_t) internal_function; +static FTSENTRY *fts_sort(FTSOBJ *, FTSENTRY *, int) internal_function; +static u_short fts_stat(FTSOBJ *, FTSENTRY *, int) internal_function; +static int fts_safe_changedir(FTSOBJ *, FTSENTRY *, int, const char *) + internal_function; + +#ifndef MAX +#define MAX(a, b) ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) +#endif + +#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) + +#define CLR(opt) (sp->fts_options &= ~(opt)) +#define ISSET(opt) (sp->fts_options & (opt)) +#define SET(opt) (sp->fts_options |= (opt)) + +#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) + +/* fts_build flags */ +#define BCHILD 1 /* fts_children */ +#define BNAMES 2 /* fts_children, names only */ +#define BREAD 3 /* fts_read */ + +FTSOBJ * +FTS_OPEN(char *const *argv, int options, + int (*compar)(const FTSENTRY **, const FTSENTRY **)) +{ + FTSOBJ *sp; + FTSENTRY *p, *root; + int nitems; + FTSENTRY *parent = NULL; + FTSENTRY *tmp; + + /* Options check. */ + if (options & ~FTS_OPTIONMASK) { + __set_errno(EINVAL); + return (NULL); + } + + /* Allocate/initialize the stream */ + if ((sp = malloc((u_int)sizeof(FTSOBJ))) == NULL) + return (NULL); + memset(sp, 0, sizeof(FTSOBJ)); + sp->fts_compar = (int (*)(const void *, const void *))compar; + sp->fts_options = options; + + /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ + if (ISSET(FTS_LOGICAL)) + SET(FTS_NOCHDIR); + + /* + * Start out with 1K of path space, and enough, in any case, + * to hold the user's paths. + */ +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + size_t maxarglen = fts_maxarglen(argv); + if (fts_palloc(sp, MAX(maxarglen, MAXPATHLEN))) + goto mem1; + + /* Allocate/initialize root's parent. */ + if (*argv != NULL) { + if ((parent = fts_alloc(sp, "", 0)) == NULL) + goto mem2; + parent->fts_level = FTS_ROOTPARENTLEVEL; + } + + /* Allocate/initialize root(s). */ + for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) { + /* Don't allow zero-length paths. */ + size_t len = strlen(*argv); + if (len == 0) { + __set_errno(ENOENT); + goto mem3; + } + + p = fts_alloc(sp, *argv, len); + p->fts_level = FTS_ROOTLEVEL; + p->fts_parent = parent; + p->fts_accpath = p->fts_name; + p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW)); + + /* Command-line "." and ".." are real directories. */ + if (p->fts_info == FTS_DOT) + p->fts_info = FTS_D; + + /* + * If comparison routine supplied, traverse in sorted + * order; otherwise traverse in the order specified. + */ + if (compar) { + p->fts_link = root; + root = p; + } else { + p->fts_link = NULL; + if (root == NULL) + tmp = root = p; + else { + tmp->fts_link = p; + tmp = p; + } + } + } + if (compar && nitems > 1) + root = fts_sort(sp, root, nitems); + + /* + * Allocate a dummy pointer and make fts_read think that we've just + * finished the node before the root(s); set p->fts_info to FTS_INIT + * so that everything about the "current" node is ignored. + */ + if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL) + goto mem3; + sp->fts_cur->fts_link = root; + sp->fts_cur->fts_info = FTS_INIT; + + /* + * If using chdir(2), grab a file descriptor pointing to dot to ensure + * that we can get back here; this could be avoided for some paths, + * but almost certainly not worth the effort. Slashes, symbolic links, + * and ".." are all fairly nasty problems. Note, if we can't get the + * descriptor we run anyway, just more slowly. + */ + if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = open(".", O_RDONLY, 0)) < 0) + SET(FTS_NOCHDIR); + + return (sp); + +mem3: + fts_lfree(root); + free(parent); +mem2: + free(sp->fts_path); +mem1: + free(sp); + return (NULL); +} + +static void + internal_function + fts_load(FTSOBJ *sp, FTSENTRY *p) +{ + int len; + char *cp; + + /* + * Load the stream structure for the next traversal. Since we don't + * actually enter the directory until after the preorder visit, set + * the fts_accpath field specially so the chdir gets done to the right + * place and the user can access the first node. From fts_open it's + * known that the path will fit. + */ + len = p->fts_pathlen = p->fts_namelen; + memmove(sp->fts_path, p->fts_name, len + 1); + if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) { + len = strlen(++cp); + memmove(p->fts_name, cp, len + 1); + p->fts_namelen = len; + } + p->fts_accpath = p->fts_path = sp->fts_path; + sp->fts_dev = p->fts_dev; +} + +int FTS_CLOSE(FTSOBJ *sp) +{ + FTSENTRY *freep, *p; + int saved_errno; + + /* + * This still works if we haven't read anything -- the dummy structure + * points to the root list, so we step through to the end of the root + * list which has a valid parent pointer. + */ + if (sp->fts_cur) { + for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) { + freep = p; + p = p->fts_link != NULL ? p->fts_link : p->fts_parent; + free(freep); + } + free(p); + } + + /* Free up child linked list, sort array, path buffer. */ + if (sp->fts_child) + fts_lfree(sp->fts_child); + free(sp->fts_array); + free(sp->fts_path); + + /* Return to original directory, save errno if necessary. */ + if (!ISSET(FTS_NOCHDIR)) { + saved_errno = fchdir(sp->fts_rfd) ? errno : 0; + (void)close(sp->fts_rfd); + + /* Set errno and return. */ + if (saved_errno != 0) { + /* Free up the stream pointer. */ + free(sp); + __set_errno(saved_errno); + return (-1); + } + } + + /* Free up the stream pointer. */ + free(sp); + return (0); +} + +/* + * Special case of "/" at the end of the path so that slashes aren't + * appended which would cause paths to be written as "....//foo". + */ +#define NAPPEND(p) \ + (p->fts_path[p->fts_pathlen - 1] == '/' \ + ? p->fts_pathlen - 1 \ + : p->fts_pathlen) + +FTSENTRY * +FTS_READ(FTSOBJ *sp) +{ + FTSENTRY *p, *tmp; + int instr; + char *t; + int saved_errno; + + /* If finished or unrecoverable error, return NULL. */ + if (sp->fts_cur == NULL || ISSET(FTS_STOP)) + return (NULL); + + /* Set current node pointer. */ + p = sp->fts_cur; + + /* Save and zero out user instructions. */ + instr = p->fts_instr; + p->fts_instr = FTS_NOINSTR; + + /* Any type of file may be re-visited; re-stat and re-turn. */ + if (instr == FTS_AGAIN) { + p->fts_info = fts_stat(sp, p, 0); + return (p); + } + + /* + * Following a symlink -- SLNONE test allows application to see + * SLNONE and recover. If indirecting through a symlink, have + * keep a pointer to current location. If unable to get that + * pointer, follow fails. + */ + if (instr == FTS_FOLLOW && + (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) { + p->fts_info = fts_stat(sp, p, 1); + if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { + if ((p->fts_symfd = open(".", O_RDONLY, 0)) < 0) { + p->fts_errno = errno; + p->fts_info = FTS_ERR; + } else + p->fts_flags |= FTS_SYMFOLLOW; + } + return (p); + } + + /* Directory in pre-order. */ + if (p->fts_info == FTS_D) { + /* If skipped or crossed mount point, do post-order visit. */ + if (instr == FTS_SKIP || + (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) { + if (p->fts_flags & FTS_SYMFOLLOW) + (void)close(p->fts_symfd); + if (sp->fts_child) { + fts_lfree(sp->fts_child); + sp->fts_child = NULL; + } + p->fts_info = FTS_DP; + return (p); + } + + /* Rebuild if only read the names and now traversing. */ + if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) { + CLR(FTS_NAMEONLY); + fts_lfree(sp->fts_child); + sp->fts_child = NULL; + } + + /* + * Cd to the subdirectory. + * + * If have already read and now fail to chdir, whack the list + * to make the names come out right, and set the parent errno + * so the application will eventually get an error condition. + * Set the FTS_DONTCHDIR flag so that when we logically change + * directories back to the parent we don't do a chdir. + * + * If haven't read do so. If the read fails, fts_build sets + * FTS_STOP or the fts_info field of the node. + */ + if (sp->fts_child != NULL) { + if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) { + p->fts_errno = errno; + p->fts_flags |= FTS_DONTCHDIR; + for (p = sp->fts_child; p != NULL; + p = p->fts_link) + p->fts_accpath = + p->fts_parent->fts_accpath; + } + } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) { + if (ISSET(FTS_STOP)) + return (NULL); + return (p); + } + p = sp->fts_child; + sp->fts_child = NULL; + sp->fts_cur = p; + goto name; + } + + /* Move to the next node on this level. */ +next: + tmp = p; + if ((p = p->fts_link) != NULL) { + sp->fts_cur = p; + free(tmp); + + /* + * If reached the top, return to the original directory (or + * the root of the tree), and load the paths for the next root. + */ + if (p->fts_level == FTS_ROOTLEVEL) { + if (FCHDIR(sp, sp->fts_rfd)) { + SET(FTS_STOP); + return (NULL); + } + fts_load(sp, p); + return p; + } + + /* + * User may have called fts_set on the node. If skipped, + * ignore. If followed, get a file descriptor so we can + * get back if necessary. + */ + if (p->fts_instr == FTS_SKIP) + goto next; + if (p->fts_instr == FTS_FOLLOW) { + p->fts_info = fts_stat(sp, p, 1); + if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) { + if ((p->fts_symfd = + open(".", O_RDONLY, 0)) < 0) { + p->fts_errno = errno; + p->fts_info = FTS_ERR; + } else + p->fts_flags |= FTS_SYMFOLLOW; + } + p->fts_instr = FTS_NOINSTR; + } + + name: + t = sp->fts_path + NAPPEND(p->fts_parent); + *t++ = '/'; + memmove(t, p->fts_name, p->fts_namelen + 1); + return p; + } + + /* Move up to the parent node. */ + p = tmp->fts_parent; + sp->fts_cur = p; + free(tmp); + + if (p->fts_level == FTS_ROOTPARENTLEVEL) { + /* + * Done; free everything up and set errno to 0 so the user + * can distinguish between error and EOF. + */ + free(p); + __set_errno(0); + return (sp->fts_cur = NULL); + } + + /* NUL terminate the pathname. */ + sp->fts_path[p->fts_pathlen] = '\0'; + + /* + * Return to the parent directory. If at a root node or came through + * a symlink, go back through the file descriptor. Otherwise, cd up + * one directory. + */ + if (p->fts_level == FTS_ROOTLEVEL) { + if (FCHDIR(sp, sp->fts_rfd)) { + SET(FTS_STOP); + return (NULL); + } + } else if (p->fts_flags & FTS_SYMFOLLOW) { + if (FCHDIR(sp, p->fts_symfd)) { + saved_errno = errno; + (void)close(p->fts_symfd); + __set_errno(saved_errno); + SET(FTS_STOP); + return (NULL); + } + (void)close(p->fts_symfd); + } else if (!(p->fts_flags & FTS_DONTCHDIR) && + fts_safe_changedir(sp, p->fts_parent, -1, "..")) { + SET(FTS_STOP); + return (NULL); + } + p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP; + return p; +} + +/* + * Fts_set takes the stream as an argument although it's not used in this + * implementation; it would be necessary if anyone wanted to add global + * semantics to fts using fts_set. An error return is allowed for similar + * reasons. + */ +/* ARGSUSED */ +int FTS_SET(FTSOBJ *sp, FTSENTRY *p, int instr) +{ + if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW && + instr != FTS_NOINSTR && instr != FTS_SKIP) { + __set_errno(EINVAL); + return (1); + } + p->fts_instr = instr; + return (0); +} + +FTSENTRY * +FTS_CHILDREN(FTSOBJ *sp, int instr) +{ + FTSENTRY *p; + int fd; + + if (instr != 0 && instr != FTS_NAMEONLY) { + __set_errno(EINVAL); + return (NULL); + } + + /* Set current node pointer. */ + p = sp->fts_cur; + + /* + * Errno set to 0 so user can distinguish empty directory from + * an error. + */ + __set_errno(0); + + /* Fatal errors stop here. */ + if (ISSET(FTS_STOP)) + return (NULL); + + /* Return logical hierarchy of user's arguments. */ + if (p->fts_info == FTS_INIT) + return (p->fts_link); + + /* + * If not a directory being visited in pre-order, stop here. Could + * allow FTS_DNR, assuming the user has fixed the problem, but the + * same effect is available with FTS_AGAIN. + */ + if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */) + return (NULL); + + /* Free up any previous child list. */ + if (sp->fts_child != NULL) + fts_lfree(sp->fts_child); + + if (instr == FTS_NAMEONLY) { + SET(FTS_NAMEONLY); + instr = BNAMES; + } else + instr = BCHILD; + + /* + * If using chdir on a relative path and called BEFORE fts_read does + * its chdir to the root of a traversal, we can lose -- we need to + * chdir into the subdirectory, and we don't know where the current + * directory is, so we can't get back so that the upcoming chdir by + * fts_read will work. + */ + if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' || + ISSET(FTS_NOCHDIR)) + return (sp->fts_child = fts_build(sp, instr)); + + if ((fd = open(".", O_RDONLY, 0)) < 0) + return (NULL); + sp->fts_child = fts_build(sp, instr); + if (fchdir(fd)) + return (NULL); + (void)close(fd); + return (sp->fts_child); +} + +static inline int +dirent_not_directory(const struct dirent *dp) +{ +#if defined DT_DIR && defined _DIRENT_HAVE_D_TYPE + return dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN; +#else + return 0; +#endif +} + +/* + * This is the tricky part -- do not casually change *anything* in here. The + * idea is to build the linked list of entries that are used by fts_children + * and fts_read. There are lots of special cases. + * + * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is + * set and it's a physical walk (so that symbolic links can't be directories), + * we can do things quickly. First, if it's a 4.4BSD file system, the type + * of the file is in the directory entry. Otherwise, we assume that the number + * of subdirectories in a node is equal to the number of links to the parent. + * The former skips all stat calls. The latter skips stat calls in any leaf + * directories and for any files after the subdirectories in the directory have + * been found, cutting the stat calls by about 2/3. + */ +static FTSENTRY * + internal_function + fts_build(FTSOBJ *sp, int type) +{ + struct dirent *dp; + FTSENTRY *p, *head; + int nitems; + FTSENTRY *cur, *tail; + DIR *dirp; + void *oldaddr; + int cderrno, descend, len, level, nlinks, saved_errno, + nostat, doadjust; + size_t maxlen; + char *cp; + + /* Set current node pointer. */ + cur = sp->fts_cur; + + /* + * Open the directory for reading. If this fails, we're done. + * If being called from fts_read, set the fts_info field. + */ +#if defined FTS_WHITEOUT && 0 + if (ISSET(FTS_WHITEOUT)) + oflag = DTF_NODUP | DTF_REWIND; + else + oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND; +#else +#define __opendir2(path, flag) opendir(path) +#endif + if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) { + if (type == BREAD) { + cur->fts_info = FTS_DNR; + cur->fts_errno = errno; + } + return (NULL); + } + + /* + * Nlinks is the number of possible entries of type directory in the + * directory if we're cheating on stat calls, 0 if we're not doing + * any stat calls at all, -1 if we're doing stats on everything. + */ + if (type == BNAMES) { + nlinks = 0; + /* Be quiet about nostat, GCC. */ + nostat = 0; + } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { + nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); + nostat = 1; + } else { + nlinks = -1; + nostat = 0; + } + +#ifdef notdef + (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); + (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n", + ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT)); +#endif + /* + * If we're going to need to stat anything or we want to descend + * and stay in the directory, chdir. If this fails we keep going, + * but set a flag so we don't chdir after the post-order visit. + * We won't be able to stat anything, but we can still return the + * names themselves. Note, that since fts_read won't be able to + * chdir into the directory, it will have to return different path + * names than before, i.e. "a/b" instead of "b". Since the node + * has already been visited in pre-order, have to wait until the + * post-order visit to return the error. There is a special case + * here, if there was nothing to stat then it's not an error to + * not be able to stat. This is all fairly nasty. If a program + * needed sorted entries or stat information, they had better be + * checking FTS_NS on the returned nodes. + */ + cderrno = 0; + if (nlinks || type == BREAD) { + if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) { + if (nlinks && type == BREAD) + cur->fts_errno = errno; + cur->fts_flags |= FTS_DONTCHDIR; + descend = 0; + cderrno = errno; + (void)closedir(dirp); + dirp = NULL; + } else + descend = 1; + } else + descend = 0; + + /* + * Figure out the max file name length that can be stored in the + * current path -- the inner loop allocates more path as necessary. + * We really wouldn't have to do the maxlen calculations here, we + * could do them in fts_read before returning the path, but it's a + * lot easier here since the length is part of the dirent structure. + * + * If not changing directories set a pointer so that can just append + * each new name into the path. + */ + len = NAPPEND(cur); + if (ISSET(FTS_NOCHDIR)) { + cp = sp->fts_path + len; + *cp++ = '/'; + } else { + /* GCC, you're too verbose. */ + cp = NULL; + } + len++; + maxlen = sp->fts_pathlen - len; + + level = cur->fts_level + 1; + + /* Read the directory, attaching each entry to the `link' pointer. */ + doadjust = 0; + for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) { + if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name)) + continue; + + if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN(dp))) == NULL) + goto mem1; + if (_D_EXACT_NAMLEN(dp) >= maxlen) { /* include space for NUL */ + oldaddr = sp->fts_path; + if (fts_palloc(sp, _D_EXACT_NAMLEN(dp) + len + 1)) { + /* + * No more memory for path or structures. Save + * errno, free up the current structure and the + * structures already allocated. + */ + mem1: + saved_errno = errno; + free(p); + fts_lfree(head); + (void)closedir(dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + __set_errno(saved_errno); + return (NULL); + } + /* Did realloc() change the pointer? */ + if (oldaddr != sp->fts_path) { + doadjust = 1; + if (ISSET(FTS_NOCHDIR)) + cp = sp->fts_path + len; + } + maxlen = sp->fts_pathlen - len; + } + + if (len + _D_EXACT_NAMLEN(dp) >= USHRT_MAX) { + /* + * In an FTSENT, fts_pathlen is a u_short so it is + * possible to wraparound here. If we do, free up + * the current structure and the structures already + * allocated, then error out with ENAMETOOLONG. + */ + free(p); + fts_lfree(head); + (void)closedir(dirp); + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + __set_errno(ENAMETOOLONG); + return (NULL); + } + p->fts_level = level; + p->fts_parent = sp->fts_cur; + p->fts_pathlen = len + _D_EXACT_NAMLEN(dp); + +#if defined FTS_WHITEOUT && 0 + if (dp->d_type == DT_WHT) + p->fts_flags |= FTS_ISW; +#endif + + /* Unreachable code. cderrno is only ever set to a nonnull + value if dirp is closed at the same time. But then we + cannot enter this loop. */ + if (0 && cderrno) { + if (nlinks) { + p->fts_info = FTS_NS; + p->fts_errno = cderrno; + } else + p->fts_info = FTS_NSOK; + p->fts_accpath = cur->fts_accpath; + } else if (nlinks == 0 || (nostat && dirent_not_directory(dp))) { + p->fts_accpath = + ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name; + p->fts_info = FTS_NSOK; + } else { + /* Build a file name for fts_stat to stat. */ + if (ISSET(FTS_NOCHDIR)) { + p->fts_accpath = p->fts_path; + memmove(cp, p->fts_name, p->fts_namelen + 1); + } else + p->fts_accpath = p->fts_name; + /* Stat it. */ + p->fts_info = fts_stat(sp, p, 0); + + /* Decrement link count if applicable. */ + if (nlinks > 0 && (p->fts_info == FTS_D || + p->fts_info == FTS_DC || p->fts_info == FTS_DOT)) + --nlinks; + } + + /* We walk in directory order so "ls -f" doesn't get upset. */ + p->fts_link = NULL; + if (head == NULL) + head = tail = p; + else { + tail->fts_link = p; + tail = p; + } + ++nitems; + } + if (dirp) + (void)closedir(dirp); + + /* + * If realloc() changed the address of the path, adjust the + * addresses for the rest of the tree and the dir list. + */ + if (doadjust) + fts_padjust(sp, head); + + /* + * If not changing directories, reset the path back to original + * state. + */ + if (ISSET(FTS_NOCHDIR)) { + if (len == sp->fts_pathlen || nitems == 0) + --cp; + *cp = '\0'; + } + + /* + * If descended after called from fts_children or after called from + * fts_read and nothing found, get back. At the root level we use + * the saved fd; if one of fts_open()'s arguments is a relative path + * to an empty directory, we wind up here with no other way back. If + * can't get back, we're done. + */ + if (descend && (type == BCHILD || !nitems) && + (cur->fts_level == FTS_ROOTLEVEL ? FCHDIR(sp, sp->fts_rfd) : fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) { + cur->fts_info = FTS_ERR; + SET(FTS_STOP); + fts_lfree(head); + return (NULL); + } + + /* If didn't find anything, return NULL. */ + if (!nitems) { + if (type == BREAD) + cur->fts_info = FTS_DP; + fts_lfree(head); + return (NULL); + } + + /* Sort the entries. */ + if (sp->fts_compar && nitems > 1) + head = fts_sort(sp, head, nitems); + return (head); +} + +static u_short + internal_function + fts_stat(FTSOBJ *sp, FTSENTRY *p, int follow) +{ + FTSENTRY *t; + dev_t dev; + INO_T ino; + struct STAT *sbp, sb; + int saved_errno; + + /* If user needs stat info, stat buffer already allocated. */ + sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; + +#if defined FTS_WHITEOUT && 0 + /* check for whiteout */ + if (p->fts_flags & FTS_ISW) { + if (sbp != &sb) { + memset(sbp, '\0', sizeof(*sbp)); + sbp->st_mode = S_IFWHT; + } + return (FTS_W); + } +#endif + + /* + * If doing a logical walk, or application requested FTS_FOLLOW, do + * a stat(2). If that fails, check for a non-existent symlink. If + * fail, set the errno from the stat call. + */ + if (ISSET(FTS_LOGICAL) || follow) { + if (STAT(p->fts_accpath, sbp)) { + saved_errno = errno; + if (!LSTAT(p->fts_accpath, sbp)) { + __set_errno(0); + return (FTS_SLNONE); + } + p->fts_errno = saved_errno; + goto err; + } + } else if (LSTAT(p->fts_accpath, sbp)) { + p->fts_errno = errno; + err: + memset(sbp, 0, sizeof(struct STAT)); + return (FTS_NS); + } + + if (S_ISDIR(sbp->st_mode)) { + /* + * Set the device/inode. Used to find cycles and check for + * crossing mount points. Also remember the link count, used + * in fts_build to limit the number of stat calls. It is + * understood that these fields are only referenced if fts_info + * is set to FTS_D. + */ + dev = p->fts_dev = sbp->st_dev; + ino = p->fts_ino = sbp->st_ino; + p->fts_nlink = sbp->st_nlink; + + if (ISDOT(p->fts_name)) + return (FTS_DOT); + + /* + * Cycle detection is done by brute force when the directory + * is first encountered. If the tree gets deep enough or the + * number of symbolic links to directories is high enough, + * something faster might be worthwhile. + */ + for (t = p->fts_parent; + t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent) + if (ino == t->fts_ino && dev == t->fts_dev) { + p->fts_cycle = t; + return (FTS_DC); + } + return (FTS_D); + } + if (S_ISLNK(sbp->st_mode)) + return (FTS_SL); + if (S_ISREG(sbp->st_mode)) + return (FTS_F); + return (FTS_DEFAULT); +} + +static FTSENTRY * + internal_function + fts_sort(FTSOBJ *sp, FTSENTRY *head, int nitems) +{ + FTSENTRY **ap, *p; + + /* + * Construct an array of pointers to the structures and call qsort(3). + * Reassemble the array in the order returned by qsort. If unable to + * sort for memory reasons, return the directory entries in their + * current order. Allocate enough space for the current needs plus + * 40 so don't realloc one entry at a time. + */ + if (nitems > sp->fts_nitems) { + FTSENTRY **a; + + sp->fts_nitems = nitems + 40; + if ((a = realloc(sp->fts_array, + (size_t)(sp->fts_nitems * sizeof(FTSENTRY *)))) == NULL) { + free(sp->fts_array); + sp->fts_array = NULL; + sp->fts_nitems = 0; + return (head); + } + sp->fts_array = a; + } + for (ap = sp->fts_array, p = head; p; p = p->fts_link) + *ap++ = p; + qsort((void *)sp->fts_array, nitems, sizeof(FTSENTRY *), sp->fts_compar); + for (head = *(ap = sp->fts_array); --nitems; ++ap) + ap[0]->fts_link = ap[1]; + ap[0]->fts_link = NULL; + return (head); +} + +static FTSENTRY * + internal_function + fts_alloc(FTSOBJ *sp, const char *name, size_t namelen) +{ + FTSENTRY *p; + size_t len; + + /* + * The file name is a variable length array and no stat structure is + * necessary if the user has set the nostat bit. Allocate the FTSENT + * structure, the file name and the stat structure in one chunk, but + * be careful that the stat structure is reasonably aligned. Since the + * fts_name field is declared to be of size 1, the fts_name pointer is + * namelen + 2 before the first possible address of the stat structure. + */ + len = sizeof(FTSENTRY) + namelen; + if (!ISSET(FTS_NOSTAT)) + len += sizeof(struct STAT) + ALIGNBYTES; + if ((p = malloc(len)) == NULL) + return (NULL); + + /* Copy the name and guarantee NUL termination. */ + memmove(p->fts_name, name, namelen); + p->fts_name[namelen] = '\0'; + + if (!ISSET(FTS_NOSTAT)) + p->fts_statp = (struct STAT *)ALIGN(p->fts_name + namelen + 2); + p->fts_namelen = namelen; + p->fts_path = sp->fts_path; + p->fts_errno = 0; + p->fts_flags = 0; + p->fts_instr = FTS_NOINSTR; + p->fts_number = 0; + p->fts_pointer = NULL; + return (p); +} + +static void + internal_function + fts_lfree(FTSENTRY *head) +{ + FTSENTRY *p; + + /* Free a linked list of structures. */ + while ((p = head)) { + head = head->fts_link; + free(p); + } +} + +/* + * Allow essentially unlimited paths; find, rm, ls should all work on any tree. + * Most systems will allow creation of paths much longer than MAXPATHLEN, even + * though the kernel won't resolve them. Add the size (not just what's needed) + * plus 256 bytes so don't realloc the path 2 bytes at a time. + */ +static int + internal_function + fts_palloc(FTSOBJ *sp, size_t more) +{ + char *p; + + sp->fts_pathlen += more + 256; + /* + * Check for possible wraparound. In an FTS, fts_pathlen is + * a signed int but in an FTSENT it is an unsigned short. + * We limit fts_pathlen to USHRT_MAX to be safe in both cases. + */ + if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) { + free(sp->fts_path); + sp->fts_path = NULL; + __set_errno(ENAMETOOLONG); + return (1); + } + p = realloc(sp->fts_path, sp->fts_pathlen); + if (p == NULL) { + free(sp->fts_path); + sp->fts_path = NULL; + return 1; + } + sp->fts_path = p; + return 0; +} + +/* + * When the path is realloc'd, have to fix all of the pointers in structures + * already returned. + */ +static void + internal_function + fts_padjust(FTSOBJ *sp, FTSENTRY *head) +{ + FTSENTRY *p; + char *addr = sp->fts_path; + +#define ADJUST(p) \ + do { \ + if ((p)->fts_accpath != (p)->fts_name) { \ + (p)->fts_accpath = \ + (char *)addr + ((p)->fts_accpath - (p)->fts_path); \ + } \ + (p)->fts_path = addr; \ + } while (0) + /* Adjust the current set of children. */ + for (p = sp->fts_child; p; p = p->fts_link) + ADJUST(p); + + /* Adjust the rest of the tree, including the current level. */ + for (p = head; p->fts_level >= FTS_ROOTLEVEL;) { + ADJUST(p); + p = p->fts_link ? p->fts_link : p->fts_parent; + } +} + +static size_t + internal_function + fts_maxarglen(char *const *argv) +{ + size_t len, max; + + for (max = 0; *argv; ++argv) + if ((len = strlen(*argv)) > max) + max = len; + return (max + 1); +} + +/* + * Change to dir specified by fd or p->fts_accpath without getting + * tricked by someone changing the world out from underneath us. + * Assumes p->fts_dev and p->fts_ino are filled in. + */ +static int + internal_function + fts_safe_changedir(FTSOBJ *sp, FTSENTRY *p, int fd, const char *path) +{ + int ret, oerrno, newfd; + struct stat sb; + + newfd = fd; + if (ISSET(FTS_NOCHDIR)) + return (0); + if (fd < 0 && (newfd = open(path, O_RDONLY, 0)) < 0) + return (-1); + if (fstat(newfd, &sb)) { + ret = -1; + goto bail; + } + if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) { + __set_errno(ENOENT); /* disinformation */ + ret = -1; + goto bail; + } + ret = fchdir(newfd); +bail: + oerrno = errno; + if (fd < 0) + (void)close(newfd); + __set_errno(oerrno); + return (ret); +} diff -Nru clamav-0.101.4+dfsg/clamonacc/misc/priv_fts.h clamav-0.102.1+dfsg/clamonacc/misc/priv_fts.h --- clamav-0.101.4+dfsg/clamonacc/misc/priv_fts.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/misc/priv_fts.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,220 @@ +#include "clamav-config.h" + +#if HAVE_SYSTEM_LFS_FTS +#include + +static inline FTSENT *_priv_fts_children(FTS *ftsp, int options) +{ + return fts_children(ftsp, options); +} + +static inline int _priv_fts_close(FTS *ftsp) +{ + return fts_close(ftsp); +} + +static inline FTS *_priv_fts_open(char *const *path_argv, int options, + int (*compar)(const FTSENT **, const FTSENT **)) +{ + return fts_open(path_argv, options, compar); +} + +static inline FTSENT *_priv_fts_read(FTS *ftsp) +{ + return fts_read(ftsp); +} + +static inline int _priv_fts_set(FTS *ftsp, FTSENT *f, int options) +{ + return fts_set(ftsp, f, options); +} + +#else +/* File tree traversal functions declarations. + Copyright (C) 1994-2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fts.h 8.3 (Berkeley) 8/14/94 + */ + +#ifndef _FTS_H +#define _FTS_H 1 + +#include + +typedef struct { + struct _ftsent *fts_cur; /* current node */ + struct _ftsent *fts_child; /* linked list of children */ + struct _ftsent **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + int fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(const void *, const void *); /* compare fn */ + +#define FTS_COMFOLLOW 0x0001 /* follow command line symlinks */ +#define FTS_LOGICAL 0x0002 /* logical walk */ +#define FTS_NOCHDIR 0x0004 /* don't change directories */ +#define FTS_NOSTAT 0x0008 /* don't get stat info */ +#define FTS_PHYSICAL 0x0010 /* physical walk */ +#define FTS_SEEDOT 0x0020 /* return dot and dot-dot */ +#define FTS_XDEV 0x0040 /* don't cross devices */ +#define FTS_WHITEOUT 0x0080 /* return whiteout information */ +#define FTS_OPTIONMASK 0x00ff /* valid user option mask */ + +#define FTS_NAMEONLY 0x0100 /* (private) child names only */ +#define FTS_STOP 0x0200 /* (private) unrecoverable error */ + int fts_options; /* fts_open options, global flags */ +} FTS; + +#ifdef __USE_LARGEFILE64 +typedef struct { + struct _ftsent64 *fts_cur; /* current node */ + struct _ftsent64 *fts_child; /* linked list of children */ + struct _ftsent64 **fts_array; /* sort array */ + dev_t fts_dev; /* starting device # */ + char *fts_path; /* path for this descent */ + int fts_rfd; /* fd for root */ + int fts_pathlen; /* sizeof(path) */ + int fts_nitems; /* elements in the sort array */ + int (*fts_compar)(const void *, const void *); /* compare fn */ + int fts_options; /* fts_open options, global flags */ +} FTS64; +#endif + +typedef struct _ftsent { + struct _ftsent *fts_cycle; /* cycle node */ + struct _ftsent *fts_parent; /* parent directory */ + struct _ftsent *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + u_short fts_pathlen; /* strlen(fts_path) */ + u_short fts_namelen; /* strlen(fts_name) */ + + ino_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ + +#define FTS_ROOTPARENTLEVEL -1 +#define FTS_ROOTLEVEL 0 + short fts_level; /* depth (-1 to N) */ + +#define FTS_D 1 /* preorder directory */ +#define FTS_DC 2 /* directory that causes cycles */ +#define FTS_DEFAULT 3 /* none of the above */ +#define FTS_DNR 4 /* unreadable directory */ +#define FTS_DOT 5 /* dot or dot-dot */ +#define FTS_DP 6 /* postorder directory */ +#define FTS_ERR 7 /* error; errno is set */ +#define FTS_F 8 /* regular file */ +#define FTS_INIT 9 /* initialized only */ +#define FTS_NS 10 /* stat(2) failed */ +#define FTS_NSOK 11 /* no stat(2) requested */ +#define FTS_SL 12 /* symbolic link */ +#define FTS_SLNONE 13 /* symbolic link without target */ +#define FTS_W 14 /* whiteout object */ + u_short fts_info; /* user flags for FTSENT structure */ + +#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */ +#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */ + u_short fts_flags; /* private flags for FTSENT structure */ + +#define FTS_AGAIN 1 /* read node again */ +#define FTS_FOLLOW 2 /* follow symbolic link */ +#define FTS_NOINSTR 3 /* no instructions */ +#define FTS_SKIP 4 /* discard node */ + u_short fts_instr; /* fts_set() instructions */ + + struct stat *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT; + +#ifdef __USE_LARGEFILE64 +typedef struct _ftsent64 { + struct _ftsent64 *fts_cycle; /* cycle node */ + struct _ftsent64 *fts_parent; /* parent directory */ + struct _ftsent64 *fts_link; /* next file in directory */ + long fts_number; /* local numeric value */ + void *fts_pointer; /* local address value */ + char *fts_accpath; /* access path */ + char *fts_path; /* root path */ + int fts_errno; /* errno for this node */ + int fts_symfd; /* fd for symlink */ + u_short fts_pathlen; /* strlen(fts_path) */ + u_short fts_namelen; /* strlen(fts_name) */ + + ino64_t fts_ino; /* inode */ + dev_t fts_dev; /* device */ + nlink_t fts_nlink; /* link count */ + + short fts_level; /* depth (-1 to N) */ + + u_short fts_info; /* user flags for FTSENT structure */ + + u_short fts_flags; /* private flags for FTSENT structure */ + + u_short fts_instr; /* fts_set() instructions */ + + struct stat64 *fts_statp; /* stat(2) information */ + char fts_name[1]; /* file name */ +} FTSENT64; +#endif + +__BEGIN_DECLS +FTSENT *_priv_fts_children(FTS *, int); +int _priv_fts_close(FTS *); +FTS *_priv_fts_open(char *const *, int, + int (*)(const FTSENT **, const FTSENT **)); +FTSENT *_priv_fts_read(FTS *); +int _priv_fts_set(FTS *, FTSENT *, int) __THROW; +__END_DECLS + +#endif /* fts.h */ +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/misc/utils.c clamav-0.102.1+dfsg/clamonacc/misc/utils.c --- clamav-0.101.4+dfsg/clamonacc/misc/utils.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/misc/utils.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include "libclamav/clamav.h" +#include "shared/optparser.h" +#include "shared/output.h" + +#include "utils.h" +#include "clamd/scanner.h" +#include "../clamonacc.h" +#include "../client/client.h" +#include "../scan/queue.h" + +#if defined(FANOTIFY) + +extern pthread_cond_t onas_scan_queue_empty_cond; + +int onas_fan_checkowner(int pid, const struct optstruct *opts) +{ + struct passwd *pwd; + char path[32]; + STATBUF sb; + const struct optstruct *opt = NULL; + const struct optstruct *opt_root = NULL; + const struct optstruct *opt_uname = NULL; + int retry = 0; + + /* always ignore ourselves */ + if (pid == (int)getpid()) { + return CHK_SELF; + } + + /* look up options */ + opt = optget(opts, "OnAccessExcludeUID"); + opt_root = optget(opts, "OnAccessExcludeRootUID"); + opt_uname = optget(opts, "OnAccessExcludeUname"); + + /* we can return immediately if no uid exclusions were requested */ + if (!(opt->enabled || opt_root->enabled || opt_uname->enabled)) + return CHK_CLEAN; + + /* perform exclusion checks if we can stat OK */ + snprintf(path, sizeof(path), "/proc/%u", pid); + if (CLAMSTAT(path, &sb) == 0) { + /* check all our non-root UIDs first */ + if (opt->enabled) { + while (opt) { + if (opt->numarg == (long long)sb.st_uid) + return CHK_FOUND; + opt = opt->nextarg; + } + } + /* then check our unames */ + if (opt_uname->enabled) { + while (opt_uname) { + errno = 0; + pwd = getpwuid(sb.st_uid); + if (NULL == pwd) { + if (errno) { + logg("*ClamMisc: internal error (failed to exclude event) ... %s\n", strerror(errno)); + switch (errno) { + case EIO: + logg("*ClamMisc: system i/o failed while retrieving username information (excluding for safety)\n"); + return CHK_FOUND; + break; + case EINTR: + logg("*ClamMisc: caught signal while retrieving username information from system (excluding for safety)\n"); + return CHK_FOUND; + break; + case EMFILE: + case ENFILE: + if (0 == retry) { + logg("*ClamMisc: waiting for consumer thread to catch up then retrying ...\n"); + sleep(3); + retry = 1; + continue; + } else { + logg("*ClamMisc: fds have been exhausted ... attempting to force the consumer thread to catch up ... (excluding for safety)\n"); + pthread_cond_signal(&onas_scan_queue_empty_cond); + sleep(3); + return CHK_FOUND; + } + case ERANGE: + default: + logg("*ClamMisc: unknown error occurred (excluding for safety)\n"); + return CHK_FOUND; + break; + } + } + } else { + if (!strncmp(opt_uname->strarg, pwd->pw_name, strlen(opt_uname->strarg))) { + return CHK_FOUND; + } + } + opt_uname = opt_uname->nextarg; + } + } + /* finally check root UID */ + if (opt_root->enabled) { + if (0 == (long long)sb.st_uid) + return CHK_FOUND; + } + } else if (errno == EACCES) { + logg("*ClamMisc: permission denied to stat /proc/%d to exclude UIDs... perhaps SELinux denial?\n", pid); + } else if (errno == ENOENT) { + /* TODO: should this be configurable? */ + logg("ClamMisc: $/proc/%d vanished before UIDs could be excluded; scanning anyway\n", pid); + } + + return CHK_CLEAN; +} + +#endif + +char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err) +{ + + FILE *opt_file = 0; + STATBUF sb; + char **opt_list = NULL; + char **rlc_ptr = NULL; + uint64_t len = 0; + int32_t ret = 0; + + *num_entries = 0; + + opt_list = cli_malloc(sizeof(char *)); + if (NULL == opt_list) { + *err = CL_EMEM; + return NULL; + } + opt_list[*num_entries] = NULL; + + errno = 0; + opt_file = fopen(fname, "r"); + + if (NULL == opt_file) { + logg("!ClamMisc: could not open path list file `%s', %s\n", fname, errno ? strerror(errno) : ""); + *err = CL_EARG; + return NULL; + } + + while ((ret = getline(opt_list + *num_entries, &len, opt_file)) != -1) { + + opt_list[*num_entries][strlen(opt_list[*num_entries]) - 1] = '\0'; + errno = 0; + if (0 != CLAMSTAT(opt_list[*num_entries], &sb)) { + logg("*ClamMisc: when parsing path list ... could not stat '%s' ... %s ... skipping\n", opt_list[*num_entries], strerror(errno)); + len = 0; + free(opt_list[*num_entries]); + opt_list[*num_entries] = NULL; + continue; + } + + if (!S_ISDIR(sb.st_mode)) { + logg("*ClamMisc: when parsing path list ... '%s' is not a directory ... skipping\n", opt_list[*num_entries]); + len = 0; + free(opt_list[*num_entries]); + opt_list[*num_entries] = NULL; + continue; + } + + if (strcmp(opt_list[*num_entries], "/") == 0) { + logg("*ClamMisc: when parsing path list ... ignoring path '%s' while DDD is enabled ... skipping\n", opt_list[*num_entries]); + logg("*ClamMisc: use the OnAccessMountPath configuration option to watch '%s'\n", opt_list[*num_entries]); + len = 0; + free(opt_list[*num_entries]); + opt_list[*num_entries] = NULL; + continue; + } + + (*num_entries)++; + rlc_ptr = cli_realloc(opt_list, sizeof(char *) * (*num_entries + 1)); + if (rlc_ptr) { + opt_list = rlc_ptr; + opt_list[*num_entries] = NULL; + } else { + *err = CL_EMEM; + fclose(opt_file); + free_opt_list(opt_list, *num_entries); + return NULL; + } + + len = 0; + } + + opt_list[*num_entries] = NULL; + fclose(opt_file); + return opt_list; +} + +void free_opt_list(char **opt_list, int entries) +{ + + int i = 0; + for (i; i < entries; i++) { + if (opt_list[i]) { + free(opt_list[i]); + opt_list[i] = NULL; + } + } + + free(opt_list); + opt_list = NULL; + + return; +} diff -Nru clamav-0.101.4+dfsg/clamonacc/misc/utils.h clamav-0.102.1+dfsg/clamonacc/misc/utils.h --- clamav-0.101.4+dfsg/clamonacc/misc/utils.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/misc/utils.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __CLAMD_ONAS_OTHERS_H +#define __CLAMD_ONAS_OTHERS_H + +#include "shared/optparser.h" +#include "libclamav/clamav.h" +#include "../clamonacc.h" + +typedef enum { + CHK_CLEAN, + CHK_FOUND, + CHK_SELF +} cli_check_t; + +#if defined(FANOTIFY) +int onas_fan_checkowner(int pid, const struct optstruct *opts); +#endif +char **onas_get_opt_list(const char *fname, int *num_entries, cl_error_t *err); +void free_opt_list(char **opt_list, int entries); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/scan/queue.c clamav-0.102.1+dfsg/clamonacc/scan/queue.c --- clamav-0.101.4+dfsg/clamonacc/scan/queue.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/scan/queue.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../misc/utils.h" + +#include "libclamav/clamav.h" + +#include "shared/optparser.h" +#include "shared/output.h" + +#include "../c-thread-pool/thpool.h" + +#include "thread.h" +#include "queue.h" + +static void onas_scan_queue_exit(void *arg); +static int onas_consume_event(threadpool thpool); +static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node); +static void onas_destroy_event_queue_node(struct onas_event_queue_node *node); + +static pthread_mutex_t onas_queue_lock = PTHREAD_MUTEX_INITIALIZER; + +static pthread_mutex_t onas_scan_queue_loop = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t onas_scan_queue_empty_cond = PTHREAD_COND_INITIALIZER; +extern pthread_t scan_queue_pid; + +static threadpool g_thpool; + +static struct onas_event_queue_node *g_onas_event_queue_head = NULL; +static struct onas_event_queue_node *g_onas_event_queue_tail = NULL; + +static struct onas_event_queue g_onas_event_queue; + +static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node) +{ + + *node = malloc(sizeof(struct onas_event_queue_node)); + if (NULL == *node) { + return CL_EMEM; + } + + **node = (struct onas_event_queue_node){ + .next = NULL, + .prev = NULL, + + .data = NULL}; + + return CL_SUCCESS; +} + +static void *onas_init_event_queue() +{ + + if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_head)) { + return NULL; + } + + if (CL_EMEM == onas_new_event_queue_node(&g_onas_event_queue_tail)) { + return NULL; + } + + g_onas_event_queue_tail->prev = g_onas_event_queue_head; + g_onas_event_queue_head->next = g_onas_event_queue_tail; + + g_onas_event_queue = (struct onas_event_queue){ + .head = g_onas_event_queue_head, + .tail = g_onas_event_queue_tail, + + .size = 0}; + + return &g_onas_event_queue; +} + +static void onas_destroy_event_queue_node(struct onas_event_queue_node *node) +{ + + if (NULL == node) { + return; + } + + node->next = NULL; + node->prev = NULL; + node->data = NULL; + + free(node); + node = NULL; + + return; +} + +static void onas_destroy_event_queue() +{ + + if (NULL == g_onas_event_queue_head) { + return; + } + + struct onas_event_queue_node *curr = g_onas_event_queue_head; + struct onas_event_queue_node *next = curr->next; + + do { + onas_destroy_event_queue_node(curr); + curr = next; + if (curr) { + next = curr->next; + } + } while (curr); + + return; +} + +void *onas_scan_queue_th(void *arg) +{ + + /* not a ton of use for context right now, but perhaps in the future we can pass in more options */ + struct onas_context *ctx = (struct onas_context *)arg; + sigset_t sigset; + struct sigaction act; + const struct optstruct *pt; + int ret, len, idx; + + cl_error_t err; + + /* ignore all signals except SIGUSR2 */ + sigfillset(&sigset); + sigdelset(&sigset, SIGUSR2); + /* The behavior of a process is undefined after it ignores a + * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */ + sigdelset(&sigset, SIGFPE); + sigdelset(&sigset, SIGILL); + sigdelset(&sigset, SIGSEGV); + sigdelset(&sigset, SIGTERM); + sigdelset(&sigset, SIGINT); +#ifdef SIGBUS + sigdelset(&sigset, SIGBUS); +#endif + + logg("*ClamScanQueue: initializing event queue consumer ... (%d) threads in thread pool\n", ctx->maxthreads); + onas_init_event_queue(); + threadpool thpool = thpool_init(ctx->maxthreads); + g_thpool = thpool; + + /* loop w/ onas_consume_event until we die */ + pthread_cleanup_push(onas_scan_queue_exit, NULL); + logg("*ClamScanQueue: waiting to consume events ...\n"); + do { + pthread_mutex_lock(&onas_scan_queue_loop); + pthread_cond_wait(&onas_scan_queue_empty_cond, &onas_scan_queue_loop); + /* run 'till we're empty */ + do { + pthread_testcancel(); + ret = onas_consume_event(thpool); + } while (1 != ret); + pthread_mutex_unlock(&onas_scan_queue_loop); + + } while (1); + + pthread_cleanup_pop(1); +} + +static int onas_queue_is_b_empty() +{ + + if (g_onas_event_queue.head->next == g_onas_event_queue.tail) { + return 1; + } + + return 0; +} + +static int onas_consume_event(threadpool thpool) +{ + + pthread_mutex_lock(&onas_queue_lock); + + struct onas_event_queue_node *popped_node = g_onas_event_queue_head->next; + + if (onas_queue_is_b_empty()) { + pthread_mutex_unlock(&onas_queue_lock); + return 1; + } + +#ifdef ONAS_DEBUG + logg("*ClamScanQueue: consuming event!\n"); +#endif + + thpool_add_work(thpool, (void *)onas_scan_worker, (void *)popped_node->data); + + g_onas_event_queue_head->next = g_onas_event_queue_head->next->next; + g_onas_event_queue_head->next->prev = g_onas_event_queue_head; + + onas_destroy_event_queue_node(popped_node); + + g_onas_event_queue.size--; + + pthread_mutex_unlock(&onas_queue_lock); + return 0; +} + +cl_error_t onas_queue_event(struct onas_scan_event *event_data) +{ + + pthread_mutex_lock(&onas_queue_lock); + + struct onas_event_queue_node *node = NULL; + +#ifdef ONAS_DEBUG + logg("*ClamScanQueue: queueing event!\n"); +#endif + + if (CL_EMEM == onas_new_event_queue_node(&node)) { + return CL_EMEM; + } + + node->next = g_onas_event_queue_tail; + node->prev = g_onas_event_queue_tail->prev; + + node->data = event_data; + + /* tail will always have a .prev */ + ((struct onas_event_queue_node *)g_onas_event_queue_tail->prev)->next = node; + g_onas_event_queue_tail->prev = node; + + g_onas_event_queue.size++; + + pthread_mutex_unlock(&onas_queue_lock); + pthread_cond_signal(&onas_scan_queue_empty_cond); + + return CL_SUCCESS; +} + +cl_error_t onas_scan_queue_start(struct onas_context **ctx) +{ + + pthread_attr_t scan_queue_attr; + int32_t thread_started = 1; + + if (!ctx || !*ctx) { + logg("*ClamScanQueue: unable to start clamonacc. (bad context)\n"); + return CL_EARG; + } + + if (pthread_attr_init(&scan_queue_attr)) { + return CL_BREAK; + } + pthread_attr_setdetachstate(&scan_queue_attr, PTHREAD_CREATE_JOINABLE); + thread_started = pthread_create(&scan_queue_pid, &scan_queue_attr, onas_scan_queue_th, *ctx); + + if (0 != thread_started) { + /* Failed to create thread */ + logg("*ClamScanQueue: Unable to start event consumer queue thread ... \n"); + return CL_ECREAT; + } + + return CL_SUCCESS; +} + +static void onas_scan_queue_exit(void *arg) +{ + + logg("*ClamScanQueue: onas_scan_queue_exit()\n"); + + pthread_mutex_lock(&onas_queue_lock); + onas_destroy_event_queue(); + + if (g_thpool) { + thpool_destroy(g_thpool); + } + g_thpool = NULL; + pthread_mutex_unlock(&onas_queue_lock); + + logg("ClamScanQueue: stopped\n"); +} diff -Nru clamav-0.101.4+dfsg/clamonacc/scan/queue.h clamav-0.102.1+dfsg/clamonacc/scan/queue.h --- clamav-0.101.4+dfsg/clamonacc/scan/queue.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/scan/queue.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_SCQUE_H +#define __ONAS_SCQUE_H + +/* extremely simple event queue implmentation w/ obj number tracking in case we want to place limits later */ +struct onas_event_queue { + struct onas_event_queue_node *head; + struct onas_event_queue_node *tail; + uint64_t size; +}; + +struct onas_event_queue_node { + struct onas_event_queue_node *next; + struct onas_event_queue_node *prev; + + struct onas_scan_event *data; +}; + +void *onas_scan_queue_th(void *arg); + +cl_error_t onas_queue_event(struct onas_scan_event *event_data); +cl_error_t onas_scan_queue_start(struct onas_context **ctx); + +#endif diff -Nru clamav-0.101.4+dfsg/clamonacc/scan/thread.c clamav-0.102.1+dfsg/clamonacc/scan/thread.c --- clamav-0.101.4+dfsg/clamonacc/scan/thread.c 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/scan/thread.c 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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 +#include +#include +#include +#include +#include +#include + +#if defined(FANOTIFY) +#include +#endif + +#include "shared/optparser.h" +#include "shared/output.h" + +#include "libclamav/others.h" +#include "../misc/priv_fts.h" +#include "../misc/utils.h" +#include "../client/client.h" +#include "thread.h" + +static pthread_mutex_t onas_scan_lock = PTHREAD_MUTEX_INITIALIZER; + +static int onas_scan(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); +static cl_error_t onas_scan_safe(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); +static cl_error_t onas_scan_thread_scanfile(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code); +static cl_error_t onas_scan_thread_handle_dir(struct onas_scan_event *event_data, const char *pathname); +static cl_error_t onas_scan_thread_handle_file(struct onas_scan_event *event_data, const char *pathname); + +static void onas_scan_thread_exit(int sig); + +static void onas_scan_thread_exit(int sig) +{ + logg("*ScanOnAccess: onas_scan_thread_exit(), signal %d\n", sig); + + pthread_exit(NULL); +} + +/** + * @brief Safe-scan wrapper, originally used by inotify and fanotify threads, now exists for error checking/convenience. + * + * Owned by scanthread to try and force multithreaded client archtiecture which better avoids kernel level deadlocks from + * fanotify blocking/prevention. + */ +static int onas_scan(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) +{ + int ret = 0; + int i = 0; + uint8_t retry_on_error = event_data->bool_opts & ONAS_SCTH_B_RETRY_ON_E; + + ret = onas_scan_safe(event_data, fname, sb, infected, err, ret_code); + + if (*err) { + switch (*ret_code) { + case CL_EACCES: + case CL_ESTAT: + + logg("*ClamMisc: internal issue (daemon could not access directory/file %s)\n", fname); + break; + /* TODO: handle other errors */ + case CL_EPARSE: + case CL_EREAD: + case CL_EWRITE: + case CL_EMEM: + case CL_ENULLARG: + default: + logg("~ClamMisc: internal issue (client failed to scan)\n"); + } + if (retry_on_error) { + logg("*ClamMisc: reattempting scan ... \n"); + while (err) { + ret = onas_scan_safe(event_data, fname, sb, infected, err, ret_code); + + i++; + if (*err && i == event_data->retry_attempts) { + *err = 0; + } + } + } + } + + return ret; +} + +/** + * @brief Thread-safe scan wrapper to ensure there's no processs contention over use of the socket. + * + * This is noticeably slower, and I had no issues running smaller scale tests with it off, but better than sorry until more testing can be done. + * + * TODO: make this configurable? + */ +static cl_error_t onas_scan_safe(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) +{ + + int ret = 0; + int fd = 0; + +#if defined(FANOTIFY) + uint8_t b_fanotify; + + b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; + + if (b_fanotify) { + fd = event_data->fmd->fd; + } +#endif + + pthread_mutex_lock(&onas_scan_lock); + + ret = onas_client_scan(event_data->tcpaddr, event_data->portnum, event_data->scantype, event_data->maxstream, + fname, fd, event_data->timeout, sb, infected, err, ret_code); + + pthread_mutex_unlock(&onas_scan_lock); + + return ret; +} + +static cl_error_t onas_scan_thread_scanfile(struct onas_scan_event *event_data, const char *fname, STATBUF sb, int *infected, int *err, cl_error_t *ret_code) +{ + +#if defined(FANOTIFY) + struct fanotify_response res; + uint8_t b_fanotify; +#endif + + int ret = 0; + + uint8_t b_scan; + uint8_t b_deny_on_error; + + if (NULL == event_data || NULL == fname || NULL == infected || NULL == err || NULL == ret_code) { + logg("!ClamWorker: scan failed (NULL arg given)\n"); + return CL_ENULLARG; + } + + b_scan = event_data->bool_opts & ONAS_SCTH_B_SCAN ? 1 : 0; + b_deny_on_error = event_data->bool_opts & ONAS_SCTH_B_DENY_ON_E ? 1 : 0; + +#if defined(FANOTIFY) + b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; + if (b_fanotify) { + res.fd = event_data->fmd->fd; + res.response = FAN_ALLOW; + } +#endif + + if (b_scan) { + ret = onas_scan(event_data, fname, sb, infected, err, ret_code); + + if (*err && *ret_code != CL_SUCCESS) { + logg("*ClamWorker: scan failed with error code %d\n", *ret_code); + } + +#if defined(FANOTIFY) + if (b_fanotify) { + if ((*err && *ret_code && b_deny_on_error) || *infected) { + res.response = FAN_DENY; + } + } +#endif + } + +#if defined(FANOTIFY) + if (b_fanotify) { + if (event_data->fmd->mask & FAN_ALL_PERM_EVENTS) { + ret = write(event_data->fan_fd, &res, sizeof(res)); + if (ret == -1) { + logg("!ClamWorker: internal error (can't write to fanotify)\n"); + if (errno == ENOENT) { + logg("*ClamWorker: permission event has already been written ... recovering ...\n"); + } else { + ret = CL_EWRITE; + } + } + } + } + + if (b_fanotify) { + +#ifdef ONAS_DEBUG + logg("*ClamWorker: closing fd, %d)\n", event_data->fmd->fd); +#endif + if (-1 == close(event_data->fmd->fd)) { + + logg("!ClamWorker: internal error (can't close fanotify meta fd, %d)\n", event_data->fmd->fd); + if (errno == EBADF) { + logg("*ClamWorker: fd already closed ... recovering ...\n"); + } else { + ret = CL_EUNLINK; + } + } + } +#endif + return ret; +} + +static cl_error_t onas_scan_thread_handle_dir(struct onas_scan_event *event_data, const char *pathname) +{ + FTS *ftsp = NULL; + int32_t ftspopts = FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV; + FTSENT *curr = NULL; + + int32_t infected = 0; + int32_t err = 0; + cl_error_t ret_code = CL_SUCCESS; + cl_error_t ret = CL_SUCCESS; + + int32_t fres = 0; + STATBUF sb; + + char *const pathargv[] = {(char *)pathname, NULL}; + + if (!(ftsp = _priv_fts_open(pathargv, ftspopts, NULL))) { + ret = CL_EOPEN; + goto out; + } + + while ((curr = _priv_fts_read(ftsp))) { + if (curr->fts_info != FTS_D) { + + fres = CLAMSTAT(curr->fts_path, &sb); + + if (event_data->sizelimit) { + if (fres != 0 || sb.st_size > event_data->sizelimit) { + /* okay to skip w/o allow/deny since dir comes from inotify + * events and (probably) won't block w/ protection enabled */ + event_data->bool_opts &= ((uint16_t)~ONAS_SCTH_B_SCAN); + logg("*ClamWorker: size limit surpassed while doing extra scanning ... skipping object ...\n"); + } + } + + ret = onas_scan_thread_scanfile(event_data, curr->fts_path, sb, &infected, &err, &ret_code); + } + } + +out: + if (ftsp) { + _priv_fts_close(ftsp); + } + + return ret; +} + +static cl_error_t onas_scan_thread_handle_file(struct onas_scan_event *event_data, const char *pathname) +{ + + STATBUF sb; + int32_t infected = 0; + int32_t err = 0; + cl_error_t ret_code = CL_SUCCESS; + int fres = 0; + cl_error_t ret = 0; + + if (NULL == pathname || NULL == event_data) { + return CL_ENULLARG; + } + + fres = CLAMSTAT(pathname, &sb); + if (event_data->sizelimit) { + if (fres != 0 || sb.st_size > event_data->sizelimit) { + /* don't skip so we avoid lockups, but don't scan either; + * while it should be obvious, this will unconditionally set + * the bit in the map to 0 regardless of original orientation */ + event_data->bool_opts &= ((uint16_t)~ONAS_SCTH_B_SCAN); + } + } + + ret = onas_scan_thread_scanfile(event_data, pathname, sb, &infected, &err, &ret_code); + +#ifdef ONAS_DEBUG + /* very noisy, debug only */ + if (event_data->bool_opts & ONAS_SCTH_B_INOTIFY) { + logg("*ClamWorker: Inotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n", + ret, infected, err, ret_code); + } else { + logg("*ClamWorker: Fanotify Scan Results ...\n\tret = %d ...\n\tinfected = %d ...\n\terr = %d ...\n\tret_code = %d\n\tfd = %d\n", + ret, infected, err, ret_code, event_data->fmd->fd); + } +#endif + + return ret; +} + +/** + * @brief worker thread designed to work with the lovely c-thread-pool library to handle our scanning jobs after our queue thread consumes an event + * + * @param arg this should always be an onas_scan_event struct + */ +void *onas_scan_worker(void *arg) +{ + + struct onas_scan_event *event_data = (struct onas_scan_event *)arg; + + uint8_t b_dir; + uint8_t b_file; + uint8_t b_inotify; + uint8_t b_fanotify; + + if (NULL == event_data || NULL == event_data->pathname) { + logg("ClamWorker: invalid worker arguments for scanning thread\n"); + if (event_data) { + logg("ClamWorker: pathname is null\n"); + } + goto done; + } + + /* load in boolean info from event struct; makes for easier reading--you're welcome */ + b_dir = event_data->bool_opts & ONAS_SCTH_B_DIR ? 1 : 0; + b_file = event_data->bool_opts & ONAS_SCTH_B_FILE ? 1 : 0; + b_inotify = event_data->bool_opts & ONAS_SCTH_B_INOTIFY ? 1 : 0; + b_fanotify = event_data->bool_opts & ONAS_SCTH_B_FANOTIFY ? 1 : 0; + +#if defined(FANOTIFY) + if (b_inotify) { + logg("*ClamWorker: handling inotify event ...\n"); + + if (b_dir) { + logg("*ClamWorker: performing (extra) scanning on directory '%s'\n", event_data->pathname); + onas_scan_thread_handle_dir(event_data, event_data->pathname); + } else if (b_file) { + logg("*ClamWorker: performing (extra) scanning on file '%s'\n", event_data->pathname); + onas_scan_thread_handle_file(event_data, event_data->pathname); + } + + } else if (b_fanotify) { + + logg("*ClamWorker: performing scanning on file '%s'\n", event_data->pathname); + onas_scan_thread_handle_file(event_data, event_data->pathname); + } else { + /* something went very wrong, so check if we have an open fd, + * try to close it to resolve any potential lingering permissions event, + * then move to cleanup */ + if (event_data->fmd) { + if (event_data->fmd->fd) { + close(event_data->fmd->fd); + goto done; + } + } + } +#endif +done: + /* our job to cleanup event data: worker queue just kicks us off in a thread pool, drops the event object + * from the queue and forgets about us */ + + if (NULL != event_data) { + if (NULL != event_data->pathname) { + free(event_data->pathname); + event_data->pathname = NULL; + } + +#if defined(FANOTIFY) + if (NULL != event_data->fmd) { + free(event_data->fmd); + event_data->fmd = NULL; + } +#endif + free(event_data); + event_data = NULL; + } + + return NULL; +} + +/** + * @brief Simple utility function for external interfaces to add relevant context information to scan_event struct. + * + * Doing this mapping cuts down significantly on memory overhead when queueing hundreds of these scan_event structs + * especially vs using a copy of a raw context struct. + * + * Other potential design options include giving the event access to the "global" context struct address instead, + * to further cut down on space used, but (among other thread safety concerns) I'd prefer the worker threads not + * have the ability to modify it at all to keep down on potential maintenance headaches in the future. + */ +cl_error_t onas_map_context_info_to_event_data(struct onas_context *ctx, struct onas_scan_event **event_data) +{ + + if (NULL == ctx || NULL == event_data || NULL == *event_data) { + logg("*ClamScThread: context and scan event struct are null ...\n"); + return CL_ENULLARG; + } + + (*event_data)->scantype = ctx->scantype; + (*event_data)->timeout = ctx->timeout; + (*event_data)->maxstream = ctx->maxstream; + (*event_data)->fan_fd = ctx->fan_fd; + (*event_data)->sizelimit = ctx->sizelimit; + (*event_data)->retry_attempts = ctx->retry_attempts; + + if (ctx->retry_on_error) { + (*event_data)->bool_opts |= ONAS_SCTH_B_RETRY_ON_E; + } + + if (ctx->deny_on_error) { + (*event_data)->bool_opts |= ONAS_SCTH_B_DENY_ON_E; + } + + if (ctx->isremote) { + (*event_data)->bool_opts |= ONAS_SCTH_B_REMOTE; + (*event_data)->tcpaddr = optget(ctx->clamdopts, "TCPAddr")->strarg; + (*event_data)->portnum = ctx->portnum; + } else { + (*event_data)->tcpaddr = optget(ctx->clamdopts, "LocalSocket")->strarg; + } + + return CL_SUCCESS; +} diff -Nru clamav-0.101.4+dfsg/clamonacc/scan/thread.h clamav-0.102.1+dfsg/clamonacc/scan/thread.h --- clamav-0.101.4+dfsg/clamonacc/scan/thread.h 1970-01-01 00:00:00.000000000 +0000 +++ clamav-0.102.1+dfsg/clamonacc/scan/thread.h 2019-11-20 04:42:24.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2015-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * Authors: Mickey Sola + * + * 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. + */ + +#ifndef __ONAS_SCTH_H +#define __ONAS_SCTH_H + +#if defined(FANOTIFY) +#include +#endif +#include "shared/optparser.h" +#include "libclamav/clamav.h" + +#define ONAS_SCTH_B_DIR 0x01 +#define ONAS_SCTH_B_FILE 0x02 +#define ONAS_SCTH_B_INOTIFY 0x04 +#define ONAS_SCTH_B_FANOTIFY 0x08 +#define ONAS_SCTH_B_SCAN 0x10 +#define ONAS_SCTH_B_RETRY_ON_E 0x20 +#define ONAS_SCTH_B_DENY_ON_E 0x40 +#define ONAS_SCTH_B_REMOTE 0x80 + +#ifndef HAVE_ATTRIB_PACKED +#define __attribute__(x) +#endif +#ifdef HAVE_PRAGMA_PACK +#pragma pack(1) +#endif +#ifdef HAVE_PRAGMA_PACK_HPPA +#pragma pack 1 +#endif + +struct onas_scan_event { + const char *tcpaddr; + int64_t portnum; + char *pathname; + int fan_fd; +#if defined(FANOTIFY) + struct fanotify_event_metadata *fmd; +#endif + uint8_t retry_attempts; + uint64_t sizelimit; + int32_t scantype; + int64_t maxstream; + int64_t timeout; + uint8_t bool_opts; +} __attribute((packed)); + +#ifdef HAVE_PRAGMA_PACK +#pragma pack() +#endif +#ifdef HAVE_PRAGMA_PACK_HPPA +#pragma pack +#endif + +void *onas_scan_th(void *arg); + +void *onas_scan_worker(void *arg); + +cl_error_t onas_map_context_info_to_event_data(struct onas_context *ctx, struct onas_scan_event **event_data); + +#endif diff -Nru clamav-0.101.4+dfsg/clamscan/Makefile.in clamav-0.102.1+dfsg/clamscan/Makefile.in --- clamav-0.101.4+dfsg/clamscan/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamscan/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -37,7 +37,17 @@ # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -103,8 +113,6 @@ target_triplet = @target@ bin_PROGRAMS = clamscan$(EXEEXT) subdir = clamscan -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -117,6 +125,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -141,7 +150,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -159,7 +169,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -175,9 +184,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -185,6 +194,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -261,6 +271,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -294,12 +305,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -331,8 +347,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -362,7 +376,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -383,6 +401,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -395,6 +414,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -406,6 +428,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -437,6 +460,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -445,6 +470,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -457,6 +483,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -486,6 +513,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -501,6 +529,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ clamscan_SOURCES = \ $(top_srcdir)/shared/output.c \ $(top_srcdir)/shared/output.h \ @@ -536,7 +565,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamscan/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamscan/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -942,6 +970,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamscan/clamscan.c clamav-0.102.1+dfsg/clamscan/clamscan.c --- clamav-0.101.4+dfsg/clamscan/clamscan.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamscan/clamscan.c 2019-11-20 04:42:24.000000000 +0000 @@ -28,7 +28,7 @@ #include #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #ifndef _WIN32 @@ -59,17 +59,17 @@ int main(int argc, char **argv) { - int ds, dms, ret; - double mb, rmb; - struct timeval t1, t2; + int ds, dms, ret; + double mb, rmb; + struct timeval t1, t2; #ifndef _WIN32 - sigset_t sigset; + sigset_t sigset; #endif - struct optstruct *opts; - const struct optstruct *opt; + struct optstruct *opts; + const struct optstruct *opt; if (check_flevel()) - exit(2); + exit(2); #if !defined(_WIN32) && !defined(C_BEOS) sigemptyset(&sigset); @@ -79,79 +79,77 @@ cl_initialize_crypto(); - - if((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) { - mprintf("!Can't parse command line options\n"); - return 2; + if ((opts = optparse(NULL, argc, argv, 1, OPT_CLAMSCAN, 0, NULL)) == NULL) { + mprintf("!Can't parse command line options\n"); + return 2; } - if(optget(opts, "verbose")->enabled) { - mprintf_verbose = 1; - logg_verbose = 1; + if (optget(opts, "verbose")->enabled) { + mprintf_verbose = 1; + logg_verbose = 1; } - if(optget(opts, "quiet")->enabled) - mprintf_quiet = 1; - - if(optget(opts, "stdout")->enabled) - mprintf_stdout = 1; + if (optget(opts, "quiet")->enabled) + mprintf_quiet = 1; + if (optget(opts, "stdout")->enabled) + mprintf_stdout = 1; - if(optget(opts, "debug")->enabled) { + if (optget(opts, "debug")->enabled) { #if defined(C_LINUX) - /* njh@bandsman.co.uk: create a dump if needed */ - struct rlimit rlim; + /* njh@bandsman.co.uk: create a dump if needed */ + struct rlimit rlim; - rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; - if(setrlimit(RLIMIT_CORE, &rlim) < 0) - perror("setrlimit"); + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_CORE, &rlim) < 0) + perror("setrlimit"); #endif - cl_debug(); /* enable debug messages */ + cl_debug(); /* enable debug messages */ } if (optget(opts, "gen-mdb")->enabled) { cl_always_gen_section_hash(); } - if(optget(opts, "version")->enabled) { - print_version(optget(opts, "database")->strarg); - optfree(opts); - return 0; + if (optget(opts, "version")->enabled) { + print_version(optget(opts, "database")->strarg); + optfree(opts); + return 0; } - if(optget(opts, "help")->enabled) { - optfree(opts); - help(); - return 0; + if (optget(opts, "help")->enabled) { + optfree(opts); + help(); + return 0; } - if(optget(opts, "recursive")->enabled) - recursion = 1; + if (optget(opts, "recursive")->enabled) + recursion = 1; - if(optget(opts, "infected")->enabled) - printinfected = 1; + if (optget(opts, "infected")->enabled) + printinfected = 1; - if(optget(opts, "suppress-ok-results")->enabled) - printclean = 0; + if (optget(opts, "suppress-ok-results")->enabled) + printclean = 0; - if(optget(opts, "bell")->enabled) - bell = 1; + if (optget(opts, "bell")->enabled) + bell = 1; /* initialize logger */ - if((opt = optget(opts, "log"))->enabled) { - logg_file = opt->strarg; - if(logg("#\n-------------------------------------------------------------------------------\n\n")) { - mprintf("!Problem with internal logger.\n"); - optfree(opts); - return 2; - } + if ((opt = optget(opts, "log"))->enabled) { + logg_file = opt->strarg; + if (logg("#\n-------------------------------------------------------------------------------\n\n")) { + mprintf("!Problem with internal logger.\n"); + optfree(opts); + return 2; + } } else - logg_file = NULL; + logg_file = NULL; - if(actsetup(opts)) { - optfree(opts); - logg_close(); - exit(2); + if (actsetup(opts)) { + optfree(opts); + logg_close(); + exit(2); } memset(&info, 0, sizeof(struct s_info)); @@ -160,38 +158,36 @@ ret = scanmanager(opts); - if(!optget(opts, "no-summary")->enabled) { - gettimeofday(&t2, NULL); + if (!optget(opts, "no-summary")->enabled) { + gettimeofday(&t2, NULL); - ds = t2.tv_sec - t1.tv_sec; - dms = t2.tv_usec - t1.tv_usec; - ds -= (dms < 0) ? (1):(0); - dms += (dms < 0) ? (1000000):(0); - logg("\n----------- SCAN SUMMARY -----------\n"); - logg("Known viruses: %u\n", info.sigs); - logg("Engine version: %s\n", get_version()); - logg("Scanned directories: %u\n", info.dirs); - logg("Scanned files: %u\n", info.files); - logg("Infected files: %u\n", info.ifiles); - if(info.errors) - logg("Total errors: %u\n", info.errors); - if(notremoved) { - logg("Not removed: %u\n", notremoved); - } - if(notmoved) { - logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved); - } - mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0; - logg("Data scanned: %2.2lf MB\n", mb); - rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0; - logg("Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks/(double)info.rblocks : 0); - logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms/1000, ds/60, ds%60); + ds = t2.tv_sec - t1.tv_sec; + dms = t2.tv_usec - t1.tv_usec; + ds -= (dms < 0) ? (1) : (0); + dms += (dms < 0) ? (1000000) : (0); + logg("\n----------- SCAN SUMMARY -----------\n"); + logg("Known viruses: %u\n", info.sigs); + logg("Engine version: %s\n", get_version()); + logg("Scanned directories: %u\n", info.dirs); + logg("Scanned files: %u\n", info.files); + logg("Infected files: %u\n", info.ifiles); + if (info.errors) + logg("Total errors: %u\n", info.errors); + if (notremoved) { + logg("Not removed: %u\n", notremoved); + } + if (notmoved) { + logg("Not %s: %u\n", optget(opts, "copy")->enabled ? "moved" : "copied", notmoved); + } + mb = info.blocks * (CL_COUNT_PRECISION / 1024) / 1024.0; + logg("Data scanned: %2.2lf MB\n", mb); + rmb = info.rblocks * (CL_COUNT_PRECISION / 1024) / 1024.0; + logg("Data read: %2.2lf MB (ratio %.2f:1)\n", rmb, info.rblocks ? (double)info.blocks / (double)info.rblocks : 0); + logg("Time: %u.%3.3u sec (%u m %u s)\n", ds, dms / 1000, ds / 60, ds % 60); } optfree(opts); - cl_cleanup_crypto(); - return ret; } @@ -212,7 +208,7 @@ mprintf(" --archive-verbose -a Show filenames inside scanned archives\n"); mprintf(" --debug Enable libclamav's debug messages\n"); mprintf(" --quiet Only output error messages\n"); - mprintf(" --stdout Write to stdout instead of stderr\n"); + mprintf(" --stdout Write to stdout instead of stderr. Does not affect 'debug' messages.\n"); mprintf(" --no-summary Disable summary at end of scanning\n"); mprintf(" --infected -i Only print infected files\n"); mprintf(" --suppress-ok-results -o Skip printing OK files\n"); diff -Nru clamav-0.101.4+dfsg/clamscan/global.h clamav-0.102.1+dfsg/clamscan/global.h --- clamav-0.101.4+dfsg/clamscan/global.h 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamscan/global.h 2019-11-20 04:42:24.000000000 +0000 @@ -23,13 +23,13 @@ #define __GLOBAL_H struct s_info { - unsigned int sigs; /* number of signatures */ - unsigned int dirs; /* number of scanned directories */ - unsigned int files; /* number of scanned files */ - unsigned int ifiles; /* number of infected files */ - unsigned int errors; /* number of errors */ - unsigned long int blocks; /* number of *scanned* 16kb blocks */ - unsigned long int rblocks; /* number of *read* 16kb blocks */ + unsigned int sigs; /* number of signatures */ + unsigned int dirs; /* number of scanned directories */ + unsigned int files; /* number of scanned files */ + unsigned int ifiles; /* number of infected files */ + unsigned int errors; /* number of errors */ + unsigned long int blocks; /* number of *scanned* 16kb blocks */ + unsigned long int rblocks; /* number of *read* 16kb blocks */ }; extern struct s_info info; diff -Nru clamav-0.101.4+dfsg/clamscan/manager.c clamav-0.102.1+dfsg/clamscan/manager.c --- clamav-0.101.4+dfsg/clamscan/manager.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamscan/manager.c 2019-11-20 04:42:24.000000000 +0000 @@ -41,7 +41,7 @@ #include #endif #include -#ifdef HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #include @@ -68,11 +68,6 @@ dev_t procdev; #endif -char hostid[37]; - -int is_valid_hostid(void); -char *get_hostid(void *cbdata); - #ifdef _WIN32 /* FIXME: If possible, handle users correctly */ static int checkaccess(const char *path, const char *username, int mode) @@ -85,36 +80,36 @@ struct passwd *user; int ret = 0, status; - if(!geteuid()) { - if((user = getpwnam(username)) == NULL) { + if (!geteuid()) { + if ((user = getpwnam(username)) == NULL) { return -1; } - switch(fork()) { - case -1: - return -2; - case 0: - if(setgid(user->pw_gid)) { - fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int) user->pw_gid); - exit(0); - } + switch (fork()) { + case -1: + return -2; + case 0: + if (setgid(user->pw_gid)) { + fprintf(stderr, "ERROR: setgid(%d) failed.\n", (int)user->pw_gid); + exit(0); + } - if(setuid(user->pw_uid)) { - fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int) user->pw_uid); - exit(0); - } + if (setuid(user->pw_uid)) { + fprintf(stderr, "ERROR: setuid(%d) failed.\n", (int)user->pw_uid); + exit(0); + } - if(access(path, mode)) - exit(0); - else - exit(1); - default: - wait(&status); - if(WIFEXITED(status) && WEXITSTATUS(status) == 1) - ret = 1; + if (access(path, mode)) + exit(0); + else + exit(1); + default: + wait(&status); + if (WIFEXITED(status) && WEXITSTATUS(status) == 1) + ret = 1; } } else { - if(!access(path, mode)) + if (!access(path, mode)) ret = 1; } @@ -131,8 +126,8 @@ }; struct clamscan_cb_data { - struct metachain * chain; - const char * filename; + struct metachain *chain; + const char *filename; }; static cl_error_t pre(int fd, const char *type, void *context) @@ -160,7 +155,7 @@ size_t i; size_t na = 0; - for (i=0;inchains-1;i++) { + for (i = 0; i < c->nchains - 1; i++) { size_t n = strlen(c->chains[i]); if (na) @@ -173,16 +168,16 @@ na += n; } - str[na] = '\0'; - str[len-1] = '\0'; + str[na] = '\0'; + str[len - 1] = '\0'; - return i == c->nchains-1 ? 0 : 1; + return i == c->nchains - 1 ? 0 : 1; } static cl_error_t post(int fd, int result, const char *virname, void *context) { struct clamscan_cb_data *d = context; - struct metachain *c = NULL; + struct metachain *c = NULL; char str[128]; UNUSEDPARAM(fd); @@ -207,8 +202,8 @@ return CL_CLEAN; } -static cl_error_t meta(const char* container_type, unsigned long fsize_container, const char *filename, - unsigned long fsize_real, int is_encrypted, unsigned int filepos_container, void *context) +static cl_error_t meta(const char *container_type, unsigned long fsize_container, const char *filename, + unsigned long fsize_real, int is_encrypted, unsigned int filepos_container, void *context) { char prev[128]; struct metachain *c; @@ -228,9 +223,9 @@ return CL_CLEAN; d = (struct clamscan_cb_data *)context; - c = d->chain; + c = d->chain; type = (strncmp(container_type, "CL_TYPE_", 8) == 0 ? container_type + 8 : container_type); - n = strlen(type) + strlen(filename) + 2; + n = strlen(type) + strlen(filename) + 2; if (!c) return CL_CLEAN; @@ -241,9 +236,9 @@ return CL_CLEAN; if (!strcmp(type, "ANY")) - snprintf(chain, n,"%s", filename); + snprintf(chain, n, "%s", filename); else - snprintf(chain, n,"%s:%s", type, filename); + snprintf(chain, n, "%s:%s", type, filename); if (c->lastadd != c->level) { n = c->nchains + 1; @@ -254,18 +249,18 @@ return CL_CLEAN; } - c->chains = chains; + c->chains = chains; c->nchains = n; c->lastadd = c->level; } else { if (c->nchains > 0) - free(c->chains[c->nchains-1]); + free(c->chains[c->nchains - 1]); } if (c->nchains > 0) { - c->chains[c->nchains-1] = chain; - toolong = print_chain(c, prev, sizeof(prev)); - logg("*Scanning %s%s!%s\n", prev,toolong ? "..." : "", chain); + c->chains[c->nchains - 1] = chain; + toolong = print_chain(c, prev, sizeof(prev)); + logg("*Scanning %s%s!%s\n", prev, toolong ? "..." : "", chain); } else { free(chain); } @@ -276,7 +271,9 @@ static void clamscan_virus_found_cb(int fd, const char *virname, void *context) { struct clamscan_cb_data *data = (struct clamscan_cb_data *)context; - const char * filename; + const char *filename; + + UNUSEDPARAM(fd); if (data == NULL) return; @@ -298,10 +295,10 @@ struct metachain chain; struct clamscan_cb_data data; - if((opt = optget(opts, "exclude"))->enabled) { - while(opt) { - if(match_regex(filename, opt->strarg) == 1) { - if(!printinfected) + if ((opt = optget(opts, "exclude"))->enabled) { + while (opt) { + if (match_regex(filename, opt->strarg) == 1) { + if (!printinfected) logg("~%s: Excluded\n", filename); return; @@ -311,11 +308,11 @@ } } - if((opt = optget(opts, "include"))->enabled) { + if ((opt = optget(opts, "include"))->enabled) { included = 0; - while(opt) { - if(match_regex(filename, opt->strarg) == 1) { + while (opt) { + if (match_regex(filename, opt->strarg) == 1) { included = 1; break; } @@ -323,8 +320,8 @@ opt = opt->nextarg; } - if(!included) { - if(!printinfected) + if (!included) { + if (!printinfected) logg("~%s: Excluded\n", filename); return; @@ -332,17 +329,17 @@ } /* argh, don't scan /proc files */ - if(CLAMSTAT(filename, &sb) != -1) { + if (CLAMSTAT(filename, &sb) != -1) { #ifdef C_LINUX - if(procdev && sb.st_dev == procdev) { - if(!printinfected) + if (procdev && sb.st_dev == procdev) { + if (!printinfected) logg("~%s: Excluded (/proc)\n", filename); return; } #endif - if(!sb.st_size) { - if(!printinfected) + if (!sb.st_size) { + if (!printinfected) logg("~%s: Empty file\n", filename); return; @@ -352,9 +349,9 @@ } #ifndef _WIN32 - if(geteuid()) { - if(checkaccess(filename, NULL, R_OK) != 1) { - if(!printinfected) + if (geteuid()) { + if (checkaccess(filename, NULL, R_OK) != 1) { + if (!printinfected) logg("~%s: Access denied\n", filename); info.errors++; @@ -364,7 +361,7 @@ #endif memset(&chain, 0, sizeof(chain)); - if(optget(opts, "archive-verbose")->enabled) { + if (optget(opts, "archive-verbose")->enabled) { chain.chains = malloc(sizeof(char **)); if (chain.chains) { chain.chains[0] = strdup(filename); @@ -380,49 +377,49 @@ logg("*Scanning %s\n", filename); - if((fd = safe_open(filename, O_RDONLY|O_BINARY)) == -1) { + if ((fd = safe_open(filename, O_RDONLY | O_BINARY)) == -1) { logg("^Can't open file %s: %s\n", filename, strerror(errno)); info.errors++; return; } - data.chain = &chain; + data.chain = &chain; data.filename = filename; - if((ret = cl_scandesc_callback(fd, filename, &virname, &info.blocks, engine, options, &data)) == CL_VIRUS) { - if(optget(opts, "archive-verbose")->enabled) { + if ((ret = cl_scandesc_callback(fd, filename, &virname, &info.blocks, engine, options, &data)) == CL_VIRUS) { + if (optget(opts, "archive-verbose")->enabled) { if (chain.nchains > 1) { char str[128]; int toolong = print_chain(&chain, str, sizeof(str)); - logg("~%s%s!(%llu)%s: %s FOUND\n", str, toolong ? "..." : "", (long long unsigned)(chain.lastvir-1), chain.chains[chain.nchains-1], virname); + logg("~%s%s!(%llu)%s: %s FOUND\n", str, toolong ? "..." : "", (long long unsigned)(chain.lastvir - 1), chain.chains[chain.nchains - 1], virname); } else if (chain.lastvir) { - logg("~%s!(%llu): %s FOUND\n", filename, (long long unsigned)(chain.lastvir-1), virname); + logg("~%s!(%llu): %s FOUND\n", filename, (long long unsigned)(chain.lastvir - 1), virname); } } info.files++; info.ifiles++; - if(bell) + if (bell) fprintf(stderr, "\007"); - } else if(ret == CL_CLEAN) { - if(!printinfected && printclean) + } else if (ret == CL_CLEAN) { + if (!printinfected && printclean) mprintf("~%s: OK\n", filename); info.files++; } else { - if(!printinfected) + if (!printinfected) logg("~%s: %s ERROR\n", filename, cl_strerror(ret)); info.errors++; } - for (i=0;ienabled) { - while(opt) { - if(match_regex(dirname, opt->strarg) == 1) { - if(!printinfected) + if ((opt = optget(opts, "exclude-dir"))->enabled) { + while (opt) { + if (match_regex(dirname, opt->strarg) == 1) { + if (!printinfected) logg("~%s: Excluded\n", dirname); return; @@ -450,10 +446,10 @@ } } - if((opt = optget(opts, "include-dir"))->enabled) { + if ((opt = optget(opts, "include-dir"))->enabled) { included = 0; - while(opt) { - if(match_regex(dirname, opt->strarg) == 1) { + while (opt) { + if (match_regex(dirname, opt->strarg) == 1) { included = 1; break; } @@ -461,26 +457,26 @@ opt = opt->nextarg; } - if(!included) { - if(!printinfected) + if (!included) { + if (!printinfected) logg("~%s: Excluded\n", dirname); return; } } - if(depth > (unsigned int) optget(opts, "max-dir-recursion")->numarg) + if (depth > (unsigned int)optget(opts, "max-dir-recursion")->numarg) return; - dirlnk = optget(opts, "follow-dir-symlinks")->numarg; + dirlnk = optget(opts, "follow-dir-symlinks")->numarg; filelnk = optget(opts, "follow-file-symlinks")->numarg; - if((dd = opendir(dirname)) != NULL) { + if ((dd = opendir(dirname)) != NULL) { info.dirs++; depth++; - while((dent = readdir(dd))) { - if(dent->d_ino) { - if(strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { + while ((dent = readdir(dd))) { + if (dent->d_ino) { + if (strcmp(dent->d_name, ".") && strcmp(dent->d_name, "..")) { /* build the full name */ fname = malloc(strlen(dirname) + strlen(dent->d_name) + 2); if (fname == NULL) { /* oops, malloc() failed, print warning and return */ @@ -488,40 +484,40 @@ break; } - if(!strcmp(dirname, PATHSEP)) - sprintf(fname, PATHSEP"%s", dent->d_name); + if (!strcmp(dirname, PATHSEP)) + sprintf(fname, PATHSEP "%s", dent->d_name); else - sprintf(fname, "%s"PATHSEP"%s", dirname, dent->d_name); + sprintf(fname, "%s" PATHSEP "%s", dirname, dent->d_name); /* stat the file */ - if(LSTAT(fname, &sb) != -1) { - if(!optget(opts, "cross-fs")->enabled) { - if(sb.st_dev != dev) { - if(!printinfected) + if (LSTAT(fname, &sb) != -1) { + if (!optget(opts, "cross-fs")->enabled) { + if (sb.st_dev != dev) { + if (!printinfected) logg("~%s: Excluded\n", fname); free(fname); continue; } } - if(S_ISLNK(sb.st_mode)) { - if(dirlnk != 2 && filelnk != 2) { - if(!printinfected) + if (S_ISLNK(sb.st_mode)) { + if (dirlnk != 2 && filelnk != 2) { + if (!printinfected) logg("%s: Symbolic link\n", fname); - } else if(CLAMSTAT(fname, &sb) != -1) { - if(S_ISREG(sb.st_mode) && filelnk == 2) { + } else if (CLAMSTAT(fname, &sb) != -1) { + if (S_ISREG(sb.st_mode) && filelnk == 2) { scanfile(fname, engine, opts, options); - } else if(S_ISDIR(sb.st_mode) && dirlnk == 2) { - if(recursion) + } else if (S_ISDIR(sb.st_mode) && dirlnk == 2) { + if (recursion) scandirs(fname, engine, opts, options, depth, dev); } else { - if(!printinfected) + if (!printinfected) logg("%s: Symbolic link\n", fname); } } - } else if(S_ISREG(sb.st_mode)) { + } else if (S_ISREG(sb.st_mode)) { scanfile(fname, engine, opts, options); - } else if(S_ISDIR(sb.st_mode) && recursion) { + } else if (S_ISDIR(sb.st_mode) && recursion) { scandirs(fname, engine, opts, options, depth, dev); } } @@ -532,7 +528,7 @@ } closedir(dd); } else { - if(!printinfected) + if (!printinfected) logg("~%s: Can't open directory.\n", dirname); info.errors++; @@ -549,32 +545,32 @@ FILE *fs; struct clamscan_cb_data data; - if(optget(opts, "tempdir")->enabled) { + if (optget(opts, "tempdir")->enabled) { tmpdir = optget(opts, "tempdir")->strarg; } else { /* check write access */ tmpdir = cli_gettmpdir(); } - if(checkaccess(tmpdir, CLAMAVUSER, W_OK) != 1) { + if (access(tmpdir, R_OK | W_OK) == -1) { logg("!Can't write to temporary directory\n"); return 2; } - if(!(file = cli_gentemp(tmpdir))) { + if (!(file = cli_gentemp(tmpdir))) { logg("!Can't generate tempfile name\n"); return 2; } - if(!(fs = fopen(file, "wb"))) { + if (!(fs = fopen(file, "wb"))) { logg("!Can't open %s for writing\n", file); free(file); return 2; } - while((bread = fread(buff, 1, FILEBUFF, stdin))) { + while ((bread = fread(buff, 1, FILEBUFF, stdin))) { fsize += bread; - if(fwrite(buff, 1, bread, fs) < bread) { + if (fwrite(buff, 1, bread, fs) < bread) { logg("!Can't write to %s\n", file); free(file); fclose(fs); @@ -590,17 +586,17 @@ info.rblocks += fsize / CL_COUNT_PRECISION; data.filename = "stdin"; - data.chain = NULL; - if((ret = cl_scanfile_callback(file, &virname, &info.blocks, engine, options, &data)) == CL_VIRUS) { + data.chain = NULL; + if ((ret = cl_scanfile_callback(file, &virname, &info.blocks, engine, options, &data)) == CL_VIRUS) { info.ifiles++; - if(bell) + if (bell) fprintf(stderr, "\007"); - } else if(ret == CL_CLEAN) { - if(!printinfected) + } else if (ret == CL_CLEAN) { + if (!printinfected) mprintf("stdin: OK\n"); } else { - if(!printinfected) + if (!printinfected) logg("stdin: %s ERROR\n", cl_strerror(ret)); info.errors++; @@ -629,46 +625,45 @@ memset(&options, 0, sizeof(struct cl_scan_options)); dirlnk = optget(opts, "follow-dir-symlinks")->numarg; - if(dirlnk > 2) { + if (dirlnk > 2) { logg("!--follow-dir-symlinks: Invalid argument\n"); return 2; } filelnk = optget(opts, "follow-file-symlinks")->numarg; - if(filelnk > 2) { + if (filelnk > 2) { logg("!--follow-file-symlinks: Invalid argument\n"); return 2; } - if(optget(opts, "yara-rules")->enabled) { - char *p = optget(opts, "yara-rules")->strarg; - if(strcmp(p, "yes")) { - if(!strcmp(p, "only")) - dboptions |= CL_DB_YARA_ONLY; - else if (!strcmp(p, "no")) - dboptions |= CL_DB_YARA_EXCLUDE; - } - + if (optget(opts, "yara-rules")->enabled) { + char *p = optget(opts, "yara-rules")->strarg; + if (strcmp(p, "yes")) { + if (!strcmp(p, "only")) + dboptions |= CL_DB_YARA_ONLY; + else if (!strcmp(p, "no")) + dboptions |= CL_DB_YARA_EXCLUDE; + } } - if(optget(opts, "phishing-sigs")->enabled) + if (optget(opts, "phishing-sigs")->enabled) dboptions |= CL_DB_PHISHING; - if(optget(opts, "official-db-only")->enabled) + if (optget(opts, "official-db-only")->enabled) dboptions |= CL_DB_OFFICIAL_ONLY; - if(optget(opts,"phishing-scan-urls")->enabled) + if (optget(opts, "phishing-scan-urls")->enabled) dboptions |= CL_DB_PHISHING_URLS; - if(optget(opts,"bytecode")->enabled) + if (optget(opts, "bytecode")->enabled) dboptions |= CL_DB_BYTECODE; - if((ret = cl_init(CL_INIT_DEFAULT))) { + if ((ret = cl_init(CL_INIT_DEFAULT))) { logg("!Can't initialize libclamav: %s\n", cl_strerror(ret)); return 2; } - if(!(engine = cl_engine_new())) { + if (!(engine = cl_engine_new())) { logg("!Can't initialize antivirus engine\n"); return 2; } @@ -678,13 +673,13 @@ if (optget(opts, "disable-cache")->enabled) cl_engine_set_num(engine, CL_ENGINE_DISABLE_CACHE, 1); - if(optget(opts, "detect-pua")->enabled) { + if (optget(opts, "detect-pua")->enabled) { dboptions |= CL_DB_PUA; - if((opt = optget(opts, "exclude-pua"))->enabled) { + if ((opt = optget(opts, "exclude-pua"))->enabled) { dboptions |= CL_DB_PUA_EXCLUDE; i = 0; - while(opt) { - if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { + while (opt) { + if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); cl_engine_free(engine); @@ -697,12 +692,12 @@ opt = opt->nextarg; } - pua_cats[i] = '.'; + pua_cats[i] = '.'; pua_cats[i + 1] = 0; } - if((opt = optget(opts, "include-pua"))->enabled) { - if(pua_cats) { + if ((opt = optget(opts, "include-pua"))->enabled) { + if (pua_cats) { logg("!--exclude-pua and --include-pua cannot be used at the same time\n"); cl_engine_free(engine); @@ -712,8 +707,8 @@ dboptions |= CL_DB_PUA_INCLUDE; i = 0; - while(opt) { - if(!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { + while (opt) { + if (!(pua_cats = realloc(pua_cats, i + strlen(opt->strarg) + 3))) { logg("!Can't allocate memory for pua_cats\n"); cl_engine_free(engine); return 2; @@ -726,12 +721,12 @@ opt = opt->nextarg; } - pua_cats[i] = '.'; + pua_cats[i] = '.'; pua_cats[i + 1] = 0; } - if(pua_cats) { - if((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) { + if (pua_cats) { + if ((ret = cl_engine_set_str(engine, CL_ENGINE_PUA_CATEGORIES, pua_cats))) { logg("!cli_engine_set_str(CL_ENGINE_PUA_CATEGORIES) failed: %s\n", cl_strerror(ret)); free(pua_cats); @@ -743,22 +738,22 @@ } } - if(optget(opts, "dev-ac-only")->enabled) + if (optget(opts, "dev-ac-only")->enabled) cl_engine_set_num(engine, CL_ENGINE_AC_ONLY, 1); - if(optget(opts, "dev-ac-depth")->enabled) + if (optget(opts, "dev-ac-depth")->enabled) cl_engine_set_num(engine, CL_ENGINE_AC_MAXDEPTH, optget(opts, "dev-ac-depth")->numarg); - if(optget(opts, "leave-temps")->enabled) + if (optget(opts, "leave-temps")->enabled) cl_engine_set_num(engine, CL_ENGINE_KEEPTMP, 1); - if(optget(opts, "force-to-disk")->enabled) + if (optget(opts, "force-to-disk")->enabled) cl_engine_set_num(engine, CL_ENGINE_FORCETODISK, 1); - if(optget(opts, "bytecode-unsigned")->enabled) + if (optget(opts, "bytecode-unsigned")->enabled) dboptions |= CL_DB_BYTECODE_UNSIGNED; - if((opt = optget(opts,"bytecode-timeout"))->enabled) + if ((opt = optget(opts, "bytecode-timeout"))->enabled) cl_engine_set_num(engine, CL_ENGINE_BYTECODE_TIMEOUT, opt->numarg); if (optget(opts, "nocerts")->enabled) @@ -767,14 +762,14 @@ if (optget(opts, "dumpcerts")->enabled) cl_engine_set_num(engine, CL_ENGINE_PE_DUMPCERTS, 1); - if((opt = optget(opts,"bytecode-mode"))->enabled) { + if ((opt = optget(opts, "bytecode-mode"))->enabled) { enum bytecode_mode mode; if (!strcmp(opt->strarg, "ForceJIT")) mode = CL_BYTECODE_MODE_JIT; - else if(!strcmp(opt->strarg, "ForceInterpreter")) + else if (!strcmp(opt->strarg, "ForceInterpreter")) mode = CL_BYTECODE_MODE_INTERPRETER; - else if(!strcmp(opt->strarg, "Test")) + else if (!strcmp(opt->strarg, "Test")) mode = CL_BYTECODE_MODE_TEST; else mode = CL_BYTECODE_MODE_AUTO; @@ -782,15 +777,14 @@ cl_engine_set_num(engine, CL_ENGINE_BYTECODE_MODE, mode); } - if((opt = optget(opts, "statistics"))->enabled) { - while(opt) { - if (!strcasecmp(opt->strarg, "bytecode")) { - dboptions |= CL_DB_BYTECODE_STATS; - } - else if (!strcasecmp(opt->strarg, "pcre")) { - dboptions |= CL_DB_PCRE_STATS; - } - opt = opt->nextarg; + if ((opt = optget(opts, "statistics"))->enabled) { + while (opt) { + if (!strcasecmp(opt->strarg, "bytecode")) { + dboptions |= CL_DB_BYTECODE_STATS; + } else if (!strcasecmp(opt->strarg, "pcre")) { + dboptions |= CL_DB_PCRE_STATS; + } + opt = opt->nextarg; } } @@ -807,8 +801,8 @@ } #endif - if((opt = optget(opts, "tempdir"))->enabled) { - if((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) { + if ((opt = optget(opts, "tempdir"))->enabled) { + if ((ret = cl_engine_set_str(engine, CL_ENGINE_TMPDIR, opt->strarg))) { logg("!cli_engine_set_str(CL_ENGINE_TMPDIR) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -816,9 +810,9 @@ } } - if((opt = optget(opts, "database"))->active) { - while(opt) { - if((ret = cl_load(opt->strarg, engine, &info.sigs, dboptions))) { + if ((opt = optget(opts, "database"))->active) { + while (opt) { + if ((ret = cl_load(opt->strarg, engine, &info.sigs, dboptions))) { logg("!%s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -830,7 +824,7 @@ } else { char *dbdir = freshdbdir(); - if((ret = cl_load(dbdir, engine, &info.sigs, dboptions))) { + if ((ret = cl_load(dbdir, engine, &info.sigs, dboptions))) { logg("!%s\n", cl_strerror(ret)); free(dbdir); @@ -858,14 +852,14 @@ } } - if((ret = cl_engine_compile(engine)) != 0) { - logg("!Database initialization error: %s\n", cl_strerror(ret));; + if ((ret = cl_engine_compile(engine)) != 0) { + logg("!Database initialization error: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 2; } - if(optget(opts, "archive-verbose")->enabled) { + if (optget(opts, "archive-verbose")->enabled) { cl_engine_set_clcb_meta(engine, meta); cl_engine_set_clcb_pre_cache(engine, pre); cl_engine_set_clcb_post_scan(engine, post); @@ -891,8 +885,8 @@ } } - if((opt = optget(opts, "max-scansize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) { + if ((opt = optget(opts, "max-scansize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCANSIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_SCANSIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -900,8 +894,8 @@ } } - if((opt = optget(opts, "max-filesize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) { + if ((opt = optget(opts, "max-filesize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILESIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_FILESIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -910,18 +904,18 @@ } #ifndef _WIN32 - if(getrlimit(RLIMIT_FSIZE, &rlim) == 0) { - if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL)) + if (getrlimit(RLIMIT_FSIZE, &rlim) == 0) { + if (rlim.rlim_cur < (rlim_t)cl_engine_get_num(engine, CL_ENGINE_MAX_FILESIZE, NULL)) logg("^System limit for file size is lower than engine->maxfilesize\n"); - if(rlim.rlim_cur < (rlim_t) cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL)) + if (rlim.rlim_cur < (rlim_t)cl_engine_get_num(engine, CL_ENGINE_MAX_SCANSIZE, NULL)) logg("^System limit for file size is lower than engine->maxscansize\n"); } else { logg("^Cannot obtain resource limits for file size\n"); } #endif - if((opt = optget(opts, "max-files"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) { + if ((opt = optget(opts, "max-files"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_FILES, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_FILES) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -929,8 +923,8 @@ } } - if((opt = optget(opts, "max-recursion"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) { + if ((opt = optget(opts, "max-recursion"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECURSION, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_RECURSION) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -940,8 +934,8 @@ /* Engine max sizes */ - if((opt = optget(opts, "max-embeddedpe"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) { + if ((opt = optget(opts, "max-embeddedpe"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_EMBEDDEDPE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_EMBEDDEDPE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -949,8 +943,8 @@ } } - if((opt = optget(opts, "max-htmlnormalize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) { + if ((opt = optget(opts, "max-htmlnormalize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNORMALIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNORMALIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -958,8 +952,8 @@ } } - if((opt = optget(opts, "max-htmlnotags"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) { + if ((opt = optget(opts, "max-htmlnotags"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_HTMLNOTAGS, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_HTMLNOTAGS) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -967,8 +961,8 @@ } } - if((opt = optget(opts, "max-scriptnormalize"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) { + if ((opt = optget(opts, "max-scriptnormalize"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_SCRIPTNORMALIZE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_SCRIPTNORMALIZE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -976,8 +970,8 @@ } } - if((opt = optget(opts, "max-ziptypercg"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) { + if ((opt = optget(opts, "max-ziptypercg"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ZIPTYPERCG, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_ZIPTYPERCG) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -985,8 +979,8 @@ } } - if((opt = optget(opts, "max-partitions"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) { + if ((opt = optget(opts, "max-partitions"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_PARTITIONS, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_PARTITIONS) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -994,8 +988,8 @@ } } - if((opt = optget(opts, "max-iconspe"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) { + if ((opt = optget(opts, "max-iconspe"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_ICONSPE, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_ICONSPE) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -1003,8 +997,8 @@ } } - if((opt = optget(opts, "max-rechwp3"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECHWP3, opt->numarg))) { + if ((opt = optget(opts, "max-rechwp3"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MAX_RECHWP3, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MAX_RECHWP3) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -1021,29 +1015,29 @@ } /* set scan options */ - if(optget(opts, "allmatch")->enabled) { + if (optget(opts, "allmatch")->enabled) { options.general |= CL_SCAN_GENERAL_ALLMATCHES; } /* TODO: Remove deprecated option in a future feature release */ - if ((optget(opts,"phishing-ssl")->enabled) || - (optget(opts,"alert-phishing-ssl")->enabled)) + if ((optget(opts, "phishing-ssl")->enabled) || + (optget(opts, "alert-phishing-ssl")->enabled)) options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_SSL_MISMATCH; /* TODO: Remove deprecated option in a future feature release */ - if ((optget(opts,"phishing-cloak")->enabled) || - (optget(opts,"alert-phishing-cloak")->enabled)) + if ((optget(opts, "phishing-cloak")->enabled) || + (optget(opts, "alert-phishing-cloak")->enabled)) options.heuristic |= CL_SCAN_HEURISTIC_PHISHING_CLOAK; /* TODO: Remove deprecated option in a future feature release */ - if ((optget(opts,"partition-intersection")->enabled) || - (optget(opts,"alert-partition-intersection")->enabled)) + if ((optget(opts, "partition-intersection")->enabled) || + (optget(opts, "alert-partition-intersection")->enabled)) options.heuristic |= CL_SCAN_HEURISTIC_PARTITION_INTXN; - if(optget(opts,"heuristic-scan-precedence")->enabled) + if (optget(opts, "heuristic-scan-precedence")->enabled) options.general |= CL_SCAN_GENERAL_HEURISTIC_PRECEDENCE; - if(optget(opts, "scan-archive")->enabled) + if (optget(opts, "scan-archive")->enabled) options.parse |= CL_SCAN_PARSE_ARCHIVE; /* TODO: Remove deprecated option in a future feature release */ @@ -1071,31 +1065,31 @@ options.heuristic |= CL_SCAN_HEURISTIC_MACROS; } - if(optget(opts, "scan-pe")->enabled) + if (optget(opts, "scan-pe")->enabled) options.parse |= CL_SCAN_PARSE_PE; - if(optget(opts, "scan-elf")->enabled) + if (optget(opts, "scan-elf")->enabled) options.parse |= CL_SCAN_PARSE_ELF; - if(optget(opts, "scan-ole2")->enabled) + if (optget(opts, "scan-ole2")->enabled) options.parse |= CL_SCAN_PARSE_OLE2; - if(optget(opts, "scan-pdf")->enabled) + if (optget(opts, "scan-pdf")->enabled) options.parse |= CL_SCAN_PARSE_PDF; - if(optget(opts, "scan-swf")->enabled) + if (optget(opts, "scan-swf")->enabled) options.parse |= CL_SCAN_PARSE_SWF; - if(optget(opts, "scan-html")->enabled && optget(opts, "normalize")->enabled) + if (optget(opts, "scan-html")->enabled && optget(opts, "normalize")->enabled) options.parse |= CL_SCAN_PARSE_HTML; - if(optget(opts, "scan-mail")->enabled) + if (optget(opts, "scan-mail")->enabled) options.parse |= CL_SCAN_PARSE_MAIL; - if(optget(opts, "scan-xmldocs")->enabled) + if (optget(opts, "scan-xmldocs")->enabled) options.parse |= CL_SCAN_PARSE_XMLDOCS; - if(optget(opts, "scan-hwp3")->enabled) + if (optget(opts, "scan-hwp3")->enabled) options.parse |= CL_SCAN_PARSE_HWP3; /* TODO: Remove deprecated option in a future feature release */ @@ -1111,37 +1105,37 @@ } #ifdef HAVE__INTERNAL__SHA_COLLECT - if(optget(opts, "dev-collect-hashes")->enabled) + if (optget(opts, "dev-collect-hashes")->enabled) options.dev |= CL_SCAN_DEV_COLLECT_SHA; #endif - if(optget(opts, "dev-performance")->enabled) + if (optget(opts, "dev-performance")->enabled) options.dev |= CL_SCAN_DEV_COLLECT_PERFORMANCE_INFO; - if(optget(opts, "detect-structured")->enabled) { + if (optget(opts, "detect-structured")->enabled) { options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED; - if((opt = optget(opts, "structured-ssn-format"))->enabled) { - switch(opt->numarg) { - case 0: - options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL; - break; - case 1: - options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED; - break; - case 2: - options.heuristic |= (CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL | CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED); - break; - default: - logg("!Invalid argument for --structured-ssn-format\n"); - return 2; + if ((opt = optget(opts, "structured-ssn-format"))->enabled) { + switch (opt->numarg) { + case 0: + options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL; + break; + case 1: + options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED; + break; + case 2: + options.heuristic |= (CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL | CL_SCAN_HEURISTIC_STRUCTURED_SSN_STRIPPED); + break; + default: + logg("!Invalid argument for --structured-ssn-format\n"); + return 2; } } else { options.heuristic |= CL_SCAN_HEURISTIC_STRUCTURED_SSN_NORMAL; } - if((opt = optget(opts, "structured-ssn-count"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) { + if ((opt = optget(opts, "structured-ssn-count"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_SSN_COUNT, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MIN_SSN_COUNT) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); @@ -1149,8 +1143,8 @@ } } - if((opt = optget(opts, "structured-cc-count"))->active) { - if((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) { + if ((opt = optget(opts, "structured-cc-count"))->active) { + if ((ret = cl_engine_set_num(engine, CL_ENGINE_MIN_CC_COUNT, opt->numarg))) { logg("!cli_engine_set_num(CL_ENGINE_MIN_CC_COUNT) failed: %s\n", cl_strerror(ret)); cl_engine_free(engine); return 2; @@ -1161,15 +1155,15 @@ } #ifdef C_LINUX - procdev = (dev_t) 0; - if(CLAMSTAT("/proc", &sb) != -1 && !sb.st_size) + procdev = (dev_t)0; + if (CLAMSTAT("/proc", &sb) != -1 && !sb.st_size) procdev = sb.st_dev; #endif /* check filetype */ - if(!opts->filename && !optget(opts, "file-list")->enabled) { + if (!opts->filename && !optget(opts, "file-list")->enabled) { /* we need full path for some reasons (eg. archive handling) */ - if(!getcwd(cwd, sizeof(cwd))) { + if (!getcwd(cwd, sizeof(cwd))) { logg("!Can't get absolute pathname of current working directory\n"); ret = 2; } else { @@ -1177,42 +1171,42 @@ scandirs(cwd, engine, opts, &options, 1, sb.st_dev); } - } else if(opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */ + } else if (opts->filename && !optget(opts, "file-list")->enabled && !strcmp(opts->filename[0], "-")) { /* read data from stdin */ ret = scanstdin(engine, opts, &options); } else { - if(opts->filename && optget(opts, "file-list")->enabled) + if (opts->filename && optget(opts, "file-list")->enabled) logg("^Only scanning files from --file-list (files passed at cmdline are ignored)\n"); - while((filename = filelist(opts, &ret)) && (file = strdup(filename))) { - if(LSTAT(file, &sb) == -1) { + while ((filename = filelist(opts, &ret)) && (file = strdup(filename))) { + if (LSTAT(file, &sb) == -1) { perror(file); logg("^%s: Can't access file\n", file); ret = 2; } else { - for(i = strlen(file) - 1; i > 0; i--) { - if(file[i] == *PATHSEP) + for (i = strlen(file) - 1; i > 0; i--) { + if (file[i] == *PATHSEP) file[i] = 0; else break; } - if(S_ISLNK(sb.st_mode)) { - if(dirlnk == 0 && filelnk == 0) { - if(!printinfected) + if (S_ISLNK(sb.st_mode)) { + if (dirlnk == 0 && filelnk == 0) { + if (!printinfected) logg("%s: Symbolic link\n", file); - } else if(CLAMSTAT(file, &sb) != -1) { - if(S_ISREG(sb.st_mode) && filelnk) { + } else if (CLAMSTAT(file, &sb) != -1) { + if (S_ISREG(sb.st_mode) && filelnk) { scanfile(file, engine, opts, &options); - } else if(S_ISDIR(sb.st_mode) && dirlnk) { + } else if (S_ISDIR(sb.st_mode) && dirlnk) { scandirs(file, engine, opts, &options, 1, sb.st_dev); } else { - if(!printinfected) + if (!printinfected) logg("%s: Symbolic link\n", file); } } - } else if(S_ISREG(sb.st_mode)) { + } else if (S_ISREG(sb.st_mode)) { scanfile(file, engine, opts, &options); - } else if(S_ISDIR(sb.st_mode)) { + } else if (S_ISDIR(sb.st_mode)) { scandirs(file, engine, opts, &options, 1, sb.st_dev); } else { logg("^%s: Not supported file type\n", file); @@ -1224,19 +1218,19 @@ } } - if((opt = optget(opts, "statistics"))->enabled) { - while(opt) { - if (!strcasecmp(opt->strarg, "bytecode")) { - cli_sigperf_print(); - cli_sigperf_events_destroy(); - } + if ((opt = optget(opts, "statistics"))->enabled) { + while (opt) { + if (!strcasecmp(opt->strarg, "bytecode")) { + cli_sigperf_print(); + cli_sigperf_events_destroy(); + } #if HAVE_PCRE - else if (!strcasecmp(opt->strarg, "pcre")) { - cli_pcre_perf_print(); - cli_pcre_perf_events_destroy(); - } + else if (!strcasecmp(opt->strarg, "pcre")) { + cli_pcre_perf_print(); + cli_pcre_perf_events_destroy(); + } #endif - opt = opt->nextarg; + opt = opt->nextarg; } } @@ -1244,46 +1238,10 @@ cl_engine_free(engine); /* overwrite return code - infection takes priority */ - if(info.ifiles) + if (info.ifiles) ret = 1; - else if(info.errors) + else if (info.errors) ret = 2; return ret; } - -int is_valid_hostid(void) -{ - int count, i; - - if (strlen(hostid) != 36) - return 0; - - count=0; - for (i=0; i < 36; i++) - if (hostid[i] == '-') - count++; - - if (count != 4) - return 0; - - if (hostid[8] != '-' || hostid[13] != '-' || hostid[18] != '-' || hostid[23] != '-') - return 0; - - return 1; -} - -char *get_hostid(void *cbdata) -{ - UNUSEDPARAM(cbdata); - - if (!strcmp(hostid, "none")) - return NULL; - - if (!is_valid_hostid()) - return strdup(STATS_ANON_UUID); - - logg("HostID is valid: %s\n", hostid); - - return strdup(hostid); -} diff -Nru clamav-0.101.4+dfsg/clamsubmit/Makefile.am clamav-0.102.1+dfsg/clamsubmit/Makefile.am --- clamav-0.101.4+dfsg/clamsubmit/Makefile.am 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamsubmit/Makefile.am 2019-11-20 04:42:24.000000000 +0000 @@ -27,12 +27,38 @@ $(top_srcdir)/shared/getopt.h \ $(top_srcdir)/shared/misc.c \ $(top_srcdir)/shared/misc.h \ + $(top_srcdir)/shared/cert_util.c \ + $(top_srcdir)/shared/cert_util.h \ + $(top_srcdir)/shared/cert_util_internal.h \ clamsubmit.c +if MACOS + clamsubmit_SOURCES += \ + $(top_srcdir)/shared/mac/cert_util_mac.m \ + $(top_srcdir)/shared/cert_util.h +endif +if WINDOWS + clamsubmit_SOURCES += \ + $(top_srcdir)/shared/win/cert_util_win.c \ + $(top_srcdir)/shared/cert_util.h +endif +if LINUX + clamsubmit_SOURCES += \ + $(top_srcdir)/shared/linux/cert_util_linux.c \ + $(top_srcdir)/shared/cert_util.h +endif + + AM_CFLAGS=@WERR_CFLAGS@ @CLAMSUBMIT_CFLAGS@ DEFS = @DEFS@ -DCL_NOTHREADS AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @SSL_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ -LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMSUBMIT_LIBS@ @THREAD_LIBS@ @JSON_LIBS@ +LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMSUBMIT_LIBS@ @THREAD_LIBS@ @JSON_LIBS@ @SSL_LIBS@ + +if MACOS +AM_LDFLAGS = -framework CoreFoundation -framework Security +endif + +AM_LIBTOOLFLAGS = --tag CXX AM_INSTALLCHECK_STD_OPTIONS_EXEMPT=clamsubmit$(EXEEXT) CLEANFILES=*.gcda *.gcno diff -Nru clamav-0.101.4+dfsg/clamsubmit/Makefile.in clamav-0.102.1+dfsg/clamsubmit/Makefile.in --- clamav-0.101.4+dfsg/clamsubmit/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamsubmit/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -33,7 +33,17 @@ # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -98,9 +108,19 @@ host_triplet = @host@ target_triplet = @target@ bin_PROGRAMS = clamsubmit$(EXEEXT) +@MACOS_TRUE@am__append_1 = \ +@MACOS_TRUE@ $(top_srcdir)/shared/mac/cert_util_mac.m \ +@MACOS_TRUE@ $(top_srcdir)/shared/cert_util.h + +@WINDOWS_TRUE@am__append_2 = \ +@WINDOWS_TRUE@ $(top_srcdir)/shared/win/cert_util_win.c \ +@WINDOWS_TRUE@ $(top_srcdir)/shared/cert_util.h + +@LINUX_TRUE@am__append_3 = \ +@LINUX_TRUE@ $(top_srcdir)/shared/linux/cert_util_linux.c \ +@LINUX_TRUE@ $(top_srcdir)/shared/cert_util.h + subdir = clamsubmit -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/config/depcomp ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -113,6 +133,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -137,7 +158,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -155,7 +177,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -171,9 +192,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -181,6 +202,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -188,8 +210,23 @@ CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" PROGRAMS = $(bin_PROGRAMS) +am__clamsubmit_SOURCES_DIST = $(top_srcdir)/shared/output.c \ + $(top_srcdir)/shared/output.h $(top_srcdir)/shared/optparser.c \ + $(top_srcdir)/shared/optparser.h $(top_srcdir)/shared/getopt.c \ + $(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/misc.c \ + $(top_srcdir)/shared/misc.h $(top_srcdir)/shared/cert_util.c \ + $(top_srcdir)/shared/cert_util.h \ + $(top_srcdir)/shared/cert_util_internal.h clamsubmit.c \ + $(top_srcdir)/shared/mac/cert_util_mac.m \ + $(top_srcdir)/shared/win/cert_util_win.c \ + $(top_srcdir)/shared/linux/cert_util_linux.c +@MACOS_TRUE@am__objects_1 = cert_util_mac.$(OBJEXT) +@WINDOWS_TRUE@am__objects_2 = cert_util_win.$(OBJEXT) +@LINUX_TRUE@am__objects_3 = cert_util_linux.$(OBJEXT) am_clamsubmit_OBJECTS = output.$(OBJEXT) optparser.$(OBJEXT) \ - getopt.$(OBJEXT) misc.$(OBJEXT) clamsubmit.$(OBJEXT) + getopt.$(OBJEXT) misc.$(OBJEXT) cert_util.$(OBJEXT) \ + clamsubmit.$(OBJEXT) $(am__objects_1) $(am__objects_2) \ + $(am__objects_3) clamsubmit_OBJECTS = $(am_clamsubmit_OBJECTS) clamsubmit_LDADD = $(LDADD) AM_V_lt = $(am__v_lt_@AM_V@) @@ -230,8 +267,26 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = +OBJCCOMPILE = $(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) +LTOBJCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(OBJC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_OBJCFLAGS) $(OBJCFLAGS) +AM_V_OBJC = $(am__v_OBJC_@AM_V@) +am__v_OBJC_ = $(am__v_OBJC_@AM_DEFAULT_V@) +am__v_OBJC_0 = @echo " OBJC " $@; +am__v_OBJC_1 = +OBJCLD = $(OBJC) +OBJCLINK = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(OBJCLD) $(AM_OBJCFLAGS) $(OBJCFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_OBJCLD = $(am__v_OBJCLD_@AM_V@) +am__v_OBJCLD_ = $(am__v_OBJCLD_@AM_DEFAULT_V@) +am__v_OBJCLD_0 = @echo " OBJCLD " $@; +am__v_OBJCLD_1 = SOURCES = $(clamsubmit_SOURCES) -DIST_SOURCES = $(clamsubmit_SOURCES) +DIST_SOURCES = $(am__clamsubmit_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -256,6 +311,7 @@ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/config/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -289,12 +345,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -326,8 +387,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -357,7 +416,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -370,7 +433,7 @@ LIBPRELUDE_LIBS = @LIBPRELUDE_LIBS@ LIBPRELUDE_PREFIX = @LIBPRELUDE_PREFIX@ LIBPRELUDE_PTHREAD_CFLAGS = @LIBPRELUDE_PTHREAD_CFLAGS@ -LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMSUBMIT_LIBS@ @THREAD_LIBS@ @JSON_LIBS@ +LIBS = $(top_builddir)/libclamav/libclamav.la @CLAMSUBMIT_LIBS@ @THREAD_LIBS@ @JSON_LIBS@ @SSL_LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ @@ -378,6 +441,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -390,6 +454,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -401,6 +468,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -432,6 +500,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -440,6 +510,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -452,6 +523,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -481,6 +553,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -496,25 +569,25 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -clamsubmit_SOURCES = \ - $(top_srcdir)/shared/output.c \ - $(top_srcdir)/shared/output.h \ - $(top_srcdir)/shared/optparser.c \ - $(top_srcdir)/shared/optparser.h \ - $(top_srcdir)/shared/getopt.c \ - $(top_srcdir)/shared/getopt.h \ - $(top_srcdir)/shared/misc.c \ - $(top_srcdir)/shared/misc.h \ - clamsubmit.c - +xmlconfig = @xmlconfig@ +clamsubmit_SOURCES = $(top_srcdir)/shared/output.c \ + $(top_srcdir)/shared/output.h $(top_srcdir)/shared/optparser.c \ + $(top_srcdir)/shared/optparser.h $(top_srcdir)/shared/getopt.c \ + $(top_srcdir)/shared/getopt.h $(top_srcdir)/shared/misc.c \ + $(top_srcdir)/shared/misc.h $(top_srcdir)/shared/cert_util.c \ + $(top_srcdir)/shared/cert_util.h \ + $(top_srcdir)/shared/cert_util_internal.h clamsubmit.c \ + $(am__append_1) $(am__append_2) $(am__append_3) AM_CFLAGS = @WERR_CFLAGS@ @CLAMSUBMIT_CFLAGS@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/shared -I$(top_srcdir)/libclamav @SSL_CPPFLAGS@ @JSON_CPPFLAGS@ @PCRE_CPPFLAGS@ +@MACOS_TRUE@AM_LDFLAGS = -framework CoreFoundation -framework Security +AM_LIBTOOLFLAGS = --tag CXX AM_INSTALLCHECK_STD_OPTIONS_EXEMPT = clamsubmit$(EXEEXT) CLEANFILES = *.gcda *.gcno all: all-am .SUFFIXES: -.SUFFIXES: .c .lo .o .obj +.SUFFIXES: .c .lo .m .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -527,7 +600,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign clamsubmit/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign clamsubmit/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -613,7 +685,7 @@ clamsubmit$(EXEEXT): $(clamsubmit_OBJECTS) $(clamsubmit_DEPENDENCIES) $(EXTRA_clamsubmit_DEPENDENCIES) @rm -f clamsubmit$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(clamsubmit_OBJECTS) $(clamsubmit_LDADD) $(LIBS) + $(AM_V_OBJCLD)$(OBJCLINK) $(clamsubmit_OBJECTS) $(clamsubmit_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -621,6 +693,10 @@ distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_util.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_util_linux.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_util_mac.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cert_util_win.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clamsubmit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ @@ -704,6 +780,83 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o misc.obj `if test -f '$(top_srcdir)/shared/misc.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/misc.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/misc.c'; fi` +cert_util.o: $(top_srcdir)/shared/cert_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util.o -MD -MP -MF $(DEPDIR)/cert_util.Tpo -c -o cert_util.o `test -f '$(top_srcdir)/shared/cert_util.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cert_util.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util.Tpo $(DEPDIR)/cert_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/cert_util.c' object='cert_util.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util.o `test -f '$(top_srcdir)/shared/cert_util.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/cert_util.c + +cert_util.obj: $(top_srcdir)/shared/cert_util.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util.obj -MD -MP -MF $(DEPDIR)/cert_util.Tpo -c -o cert_util.obj `if test -f '$(top_srcdir)/shared/cert_util.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cert_util.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cert_util.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util.Tpo $(DEPDIR)/cert_util.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/cert_util.c' object='cert_util.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util.obj `if test -f '$(top_srcdir)/shared/cert_util.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/cert_util.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/cert_util.c'; fi` + +cert_util_win.o: $(top_srcdir)/shared/win/cert_util_win.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util_win.o -MD -MP -MF $(DEPDIR)/cert_util_win.Tpo -c -o cert_util_win.o `test -f '$(top_srcdir)/shared/win/cert_util_win.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/win/cert_util_win.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_win.Tpo $(DEPDIR)/cert_util_win.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/win/cert_util_win.c' object='cert_util_win.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util_win.o `test -f '$(top_srcdir)/shared/win/cert_util_win.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/win/cert_util_win.c + +cert_util_win.obj: $(top_srcdir)/shared/win/cert_util_win.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util_win.obj -MD -MP -MF $(DEPDIR)/cert_util_win.Tpo -c -o cert_util_win.obj `if test -f '$(top_srcdir)/shared/win/cert_util_win.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/win/cert_util_win.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/win/cert_util_win.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_win.Tpo $(DEPDIR)/cert_util_win.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/win/cert_util_win.c' object='cert_util_win.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util_win.obj `if test -f '$(top_srcdir)/shared/win/cert_util_win.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/win/cert_util_win.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/win/cert_util_win.c'; fi` + +cert_util_linux.o: $(top_srcdir)/shared/linux/cert_util_linux.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util_linux.o -MD -MP -MF $(DEPDIR)/cert_util_linux.Tpo -c -o cert_util_linux.o `test -f '$(top_srcdir)/shared/linux/cert_util_linux.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/linux/cert_util_linux.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_linux.Tpo $(DEPDIR)/cert_util_linux.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/linux/cert_util_linux.c' object='cert_util_linux.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util_linux.o `test -f '$(top_srcdir)/shared/linux/cert_util_linux.c' || echo '$(srcdir)/'`$(top_srcdir)/shared/linux/cert_util_linux.c + +cert_util_linux.obj: $(top_srcdir)/shared/linux/cert_util_linux.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_util_linux.obj -MD -MP -MF $(DEPDIR)/cert_util_linux.Tpo -c -o cert_util_linux.obj `if test -f '$(top_srcdir)/shared/linux/cert_util_linux.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/linux/cert_util_linux.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/linux/cert_util_linux.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_linux.Tpo $(DEPDIR)/cert_util_linux.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/shared/linux/cert_util_linux.c' object='cert_util_linux.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cert_util_linux.obj `if test -f '$(top_srcdir)/shared/linux/cert_util_linux.c'; then $(CYGPATH_W) '$(top_srcdir)/shared/linux/cert_util_linux.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/linux/cert_util_linux.c'; fi` + +.m.o: +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ $< + +.m.obj: +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJCCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.m.lo: +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(LTOBJCCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(LTOBJCCOMPILE) -c -o $@ $< + +cert_util_mac.o: $(top_srcdir)/shared/mac/cert_util_mac.m +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -MT cert_util_mac.o -MD -MP -MF $(DEPDIR)/cert_util_mac.Tpo -c -o cert_util_mac.o `test -f '$(top_srcdir)/shared/mac/cert_util_mac.m' || echo '$(srcdir)/'`$(top_srcdir)/shared/mac/cert_util_mac.m +@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_mac.Tpo $(DEPDIR)/cert_util_mac.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$(top_srcdir)/shared/mac/cert_util_mac.m' object='cert_util_mac.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -c -o cert_util_mac.o `test -f '$(top_srcdir)/shared/mac/cert_util_mac.m' || echo '$(srcdir)/'`$(top_srcdir)/shared/mac/cert_util_mac.m + +cert_util_mac.obj: $(top_srcdir)/shared/mac/cert_util_mac.m +@am__fastdepOBJC_TRUE@ $(AM_V_OBJC)$(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -MT cert_util_mac.obj -MD -MP -MF $(DEPDIR)/cert_util_mac.Tpo -c -o cert_util_mac.obj `if test -f '$(top_srcdir)/shared/mac/cert_util_mac.m'; then $(CYGPATH_W) '$(top_srcdir)/shared/mac/cert_util_mac.m'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/mac/cert_util_mac.m'; fi` +@am__fastdepOBJC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/cert_util_mac.Tpo $(DEPDIR)/cert_util_mac.Po +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ $(AM_V_OBJC)source='$(top_srcdir)/shared/mac/cert_util_mac.m' object='cert_util_mac.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepOBJC_FALSE@ DEPDIR=$(DEPDIR) $(OBJCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepOBJC_FALSE@ $(AM_V_OBJC@am__nodep@)$(OBJC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_OBJCFLAGS) $(OBJCFLAGS) -c -o cert_util_mac.obj `if test -f '$(top_srcdir)/shared/mac/cert_util_mac.m'; then $(CYGPATH_W) '$(top_srcdir)/shared/mac/cert_util_mac.m'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/shared/mac/cert_util_mac.m'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -917,6 +1070,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/clamsubmit/clamsubmit.c clamav-0.102.1+dfsg/clamsubmit/clamsubmit.c --- clamav-0.101.4+dfsg/clamsubmit/clamsubmit.c 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/clamsubmit/clamsubmit.c 2019-11-20 04:42:24.000000000 +0000 @@ -1,16 +1,27 @@ #include #include +#if HAVE_UNISTD_H #include +#endif #include +#ifdef _WIN32 +#include +#include +#endif + #include +#include "target.h" #include "libclamav/clamav.h" #include "libclamav/others.h" #include "shared/misc.h" #include "shared/getopt.h" +#if defined(C_DARWIN) || defined(_WIN32) +#include "shared/cert_util.h" +#endif -#define OPTS "e:p:n:N:V:H:h?v" +#define OPTS "e:p:n:N:V:H:h?v?d" char *read_stream(void); void usage(char *name); @@ -18,23 +29,25 @@ typedef struct _header_data { int len; - char * cfduid; - char * session; + char *cfduid; + char *session; } header_data; typedef struct _write_data { int len; - char * str; + char *str; } write_data; +int g_debug = 0; + void usage(char *name) { printf("\n"); - printf(" Clam AntiVirus: Monitoring Tool %s\n", get_version()); + printf(" Clam AntiVirus: Malware and False Positive Reporting Tool %s\n", get_version()); printf(" By The ClamAV Team: https://www.clamav.net/about.html#credits\n"); printf(" (C) 2019 Cisco Systems, Inc.\n"); printf("\n"); - printf(" %s -hHinpVv?\n", name); + printf(" %s -hHinpVvd?\n", name); printf("\n"); printf(" -h or -? Show this help\n"); printf(" -v Show version\n"); @@ -43,6 +56,7 @@ printf(" -N [NAME] Your name contained in quotation marks (required)\n"); printf(" -p [FILE/-] Submit a false positive (FP)\n"); printf(" -V [VIRUS] Detected virus name (required with -p)\n"); + printf(" -d Enable debug output\n"); printf("\n"); printf("You must specify -n or -p. Both are mutually exclusive. Pass in - as the filename for stdin.\n\n"); exit(0); @@ -56,11 +70,11 @@ size_t header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) { - int len = size*nmemb; + int len = size * nmemb; char *sp, *ep, *mem; - header_data *hd = (header_data *) userdata; + header_data *hd = (header_data *)userdata; const char *set_cookie = "Set-Cookie:"; - int clen = strlen(set_cookie); + int clen = strlen(set_cookie); if (len > clen) { if (strncmp(ptr, set_cookie, clen)) @@ -71,13 +85,13 @@ fprintf(stderr, "header_cb(): malformed cookie\n"); return 0; } - mem = malloc(ep-sp+1); + mem = malloc(ep - sp + 1); if (mem == NULL) { fprintf(stderr, "header_cb(): malloc failed\n"); return 0; } - memcpy(mem, sp, ep-sp); - mem[ep-sp] = '\0'; + memcpy(mem, sp, ep - sp); + mem[ep - sp] = '\0'; if (!strncmp(mem, "__cfduid", 8)) hd->cfduid = mem; else if (!strncmp(mem, "_clamav-net_session", strlen("_clamav-net_session"))) @@ -90,19 +104,19 @@ size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) { - int len = size*nmemb; - char * str; - write_data *wd = (write_data *) userdata; + int len = size * nmemb; + char *str; + write_data *wd = (write_data *)userdata; if (len) { str = realloc(wd->str, wd->len + len + 1); if (str == NULL) { - fprintf (stderr, "write_cb() realloc failure\n"); + fprintf(stderr, "write_cb() realloc failure\n"); return 0; } memcpy(str + wd->len, ptr, len); str[wd->len + len] = '\0'; - wd->str = str; + wd->str = str; wd->len += len; } return len; @@ -110,15 +124,15 @@ /** * @brief Parse a value from a JSON object, given a key. - * + * * @param ps_json_obj The JSON object * @param key The Key * @return const char* The Value on Success, NULL on Failure. */ -const char* presigned_get_string(json_object * ps_json_obj, char * key) +const char *presigned_get_string(json_object *ps_json_obj, char *key) { - json_object * json_obj = NULL; - const char * json_str = NULL; + json_object *json_obj = NULL; + const char *json_str = NULL; if (json_object_object_get_ex(ps_json_obj, key, &json_obj)) { json_str = json_object_get_string(json_obj); @@ -134,26 +148,26 @@ int main(int argc, char *argv[]) { int status = 1; + char userAgent[128]; CURL *clam_curl = NULL, *aws_curl = NULL; CURLcode res; int ch; - struct curl_httppost *post=NULL, *last=NULL; + struct curl_httppost *post = NULL, *last = NULL; struct curl_slist *slist = NULL; - char *name=NULL, *email=NULL, *filename=NULL; - int setURL=0, fromStream=0; - const char * json_str; - write_data wd = {0, NULL}; - header_data hd_malware = {0, NULL, NULL}; + char *name = NULL, *email = NULL, *filename = NULL; + int setURL = 0, fromStream = 0; + const char *json_str; + write_data wd = {0, NULL}; + header_data hd_malware = {0, NULL, NULL}; header_data hd_presigned = {0, NULL, NULL}; - json_object * ps_json_obj = NULL; - json_object * json_obj = NULL; - int malware = 0; - int len = 0; - char * submissionID = NULL; - char * fpvname = NULL; + json_object *ps_json_obj = NULL; + int malware = 0; + int len = 0; + char *submissionID = NULL; + char *fpvname = NULL; char *sp, *ep, *str; - char * authenticity_token = NULL; - char * urlp; + char *authenticity_token = NULL; + char *urlp; curl_global_init(CURL_GLOBAL_ALL); @@ -163,6 +177,16 @@ goto cleanup; } + memset(userAgent, 0, sizeof(userAgent)); + snprintf(userAgent, sizeof(userAgent), + PACKAGE "/%s (OS: " TARGET_OS_TYPE ", ARCH: " TARGET_ARCH_TYPE ", CPU: " TARGET_CPU_TYPE ")", + get_version()); + userAgent[sizeof(userAgent) - 1] = 0; + + if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_USERAGENT, userAgent)) { + fprintf(stderr, "!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); + } + while ((ch = my_getopt(argc, argv, OPTS)) > 0) { switch (ch) { case 'v': @@ -182,12 +206,15 @@ case 'n': if (setURL) usage(argv[0]); - malware = 1; + malware = 1; filename = optarg; break; case 'V': fpvname = optarg; break; + case 'd': + g_debug = 1; + break; case 'h': case '?': default: @@ -208,9 +235,28 @@ fprintf(stderr, "ERROR: Unable to read stream\n"); goto cleanup; } - fromStream=1; + fromStream = 1; + } + + if (g_debug) { + /* ask libcurl to show us the verbose output */ + if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_VERBOSE, 1L)) { + fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); + } + if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_STDERR, stdout)) { + fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); + } } + if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { + fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); + } + +#if defined(C_DARWIN) || defined(_WIN32) + if (CURLE_OK != curl_easy_setopt(clam_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { + fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); + } +#endif /*** The GET malware|fp ***/ if (malware == 1) @@ -225,39 +271,38 @@ curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); res = curl_easy_perform(clam_curl); if (res != CURLE_OK) { - fprintf(stderr, "Error in GET %s: %s\n", urlp , curl_easy_strerror(res)); + fprintf(stderr, "Error in GET %s: %s\n", urlp, curl_easy_strerror(res)); goto cleanup; } if (wd.str != NULL) { sp = strstr(wd.str, "name=\"authenticity_token\""); if (sp == NULL) { - fprintf (stderr, "Authenticity token element not found.\n"); + fprintf(stderr, "Authenticity token element not found.\n"); goto cleanup; } sp = strstr(sp, "value="); if (sp == NULL) { - fprintf (stderr, "Authenticity token value not found.\n"); + fprintf(stderr, "Authenticity token value not found.\n"); goto cleanup; } sp += 7; ep = strchr(sp, '"'); if (ep == NULL) { - fprintf (stderr, "Authenticity token malformed.\n"); + fprintf(stderr, "Authenticity token malformed.\n"); goto cleanup; } - authenticity_token = malloc(ep-sp+1); + authenticity_token = malloc(ep - sp + 1); if (authenticity_token == NULL) { - fprintf (stderr, "no memory for authenticity token.\n"); + fprintf(stderr, "no memory for authenticity token.\n"); goto cleanup; } - memcpy(authenticity_token, sp, ep-sp); - authenticity_token[ep-sp] = '\0'; - free (wd.str); + memcpy(authenticity_token, sp, ep - sp); + authenticity_token[ep - sp] = '\0'; + free(wd.str); wd.str = NULL; } wd.len = 0; - urlp = NULL; - + urlp = NULL; /*** The GET presigned ***/ if (malware == 1) @@ -267,7 +312,7 @@ curl_easy_setopt(clam_curl, CURLOPT_HTTPGET, 1); if (NULL == hd_malware.cfduid || NULL == hd_malware.session) { - fprintf (stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission."); + fprintf(stderr, "invalid cfduid and/or session id values provided by clamav.net/presigned. Unable to continue submission."); goto cleanup; } @@ -300,7 +345,7 @@ curl_easy_setopt(clam_curl, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(clam_curl, CURLOPT_HEADERDATA, &hd_presigned); curl_easy_setopt(clam_curl, CURLOPT_HEADERFUNCTION, header_cb); - if (malware ==1) + if (malware == 1) curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/malware"); else curl_easy_setopt(clam_curl, CURLOPT_REFERER, "https://www.clamav.net/reports/fp"); @@ -313,7 +358,6 @@ curl_slist_free_all(slist); slist = NULL; - /*** The POST to AWS ***/ ps_json_obj = json_tokener_parse(wd.str); if (ps_json_obj == NULL) { @@ -336,19 +380,45 @@ fprintf(stderr, "Error: malformed 'key' string in GET presigned response (missing '-'.\n"); goto cleanup; } - submissionID = malloc(ep-sp+1); + + submissionID = malloc(ep - sp + 1); if (submissionID == NULL) { fprintf(stderr, "Error: malloc submissionID.\n"); goto cleanup; } - memcpy(submissionID, sp, ep-sp); - submissionID[ep-sp] = '\0'; + memcpy(submissionID, sp, ep - sp); + submissionID[ep - sp] = '\0'; + aws_curl = curl_easy_init(); if (!(aws_curl)) { fprintf(stderr, "ERROR: Could not initialize libcurl POST presigned\n"); goto cleanup; } - submissionID[ep-sp] = '\0'; + + if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_USERAGENT, userAgent)) { + fprintf(stderr, "!create_curl_handle: Failed to set CURLOPT_USERAGENT (%s)!\n", userAgent); + } + + if (g_debug) { + /* ask libcurl to show us the verbose output */ + if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_VERBOSE, 1L)) { + fprintf(stderr, "!ERROR: Failed to set CURLOPT_VERBOSE!\n"); + } + if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_STDERR, stdout)) { + fprintf(stderr, "!ERROR: Failed to direct curl debug output to stdout!\n"); + } + } + + if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1)) { + fprintf(stderr, "ERROR: Failed to set HTTP version to 1.1 (to prevent 2.0 responses which we don't yet parse properly)!\n"); + } + +#if defined(C_DARWIN) || defined(_WIN32) + if (CURLE_OK != curl_easy_setopt(aws_curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function)) { + fprintf(stderr, "ERROR: Failed to set SSL CTX function!\n"); + } +#endif + curl_formadd(&post, &last, CURLFORM_COPYNAME, "key", CURLFORM_COPYCONTENTS, json_str, CURLFORM_END); json_str = presigned_get_string(ps_json_obj, "acl"); @@ -424,11 +494,10 @@ wd.str = NULL; wd.len = 0; - /*** The POST submit to clamav.net ***/ slist = curl_slist_append(slist, "Expect:"); - len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; - str = malloc(len); + len = strlen(hd_malware.cfduid) + strlen(hd_malware.session) + 3; + str = malloc(len); if (str == NULL) { fprintf(stderr, "No memory for POST submit cookies.\n"); goto cleanup; @@ -440,17 +509,17 @@ } curl_easy_setopt(clam_curl, CURLOPT_COOKIE, str); free(str); - curl_formadd(&post, &last, CURLFORM_COPYNAME, "utf8", CURLFORM_COPYCONTENTS, "\x27" "\x13", CURLFORM_END); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "utf8", CURLFORM_COPYCONTENTS, "\x27\x13", CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "authenticity_token", CURLFORM_COPYCONTENTS, authenticity_token, CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "submissionID", CURLFORM_COPYCONTENTS, submissionID, CURLFORM_END); - curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware?"malware":"fp", CURLFORM_END); + curl_formadd(&post, &last, CURLFORM_COPYNAME, "type", CURLFORM_COPYCONTENTS, malware ? "malware" : "fp", CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "sendername", CURLFORM_COPYCONTENTS, name, CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "email", CURLFORM_COPYCONTENTS, email, CURLFORM_END); if (malware == 0) { curl_formadd(&post, &last, CURLFORM_COPYNAME, "virusname", CURLFORM_COPYCONTENTS, fpvname, CURLFORM_END); } else { - if (malware == 1) - curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); + if (malware == 1) + curl_formadd(&post, &last, CURLFORM_COPYNAME, "shareSample", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); } curl_formadd(&post, &last, CURLFORM_COPYNAME, "description", CURLFORM_COPYCONTENTS, "clamsubmit", CURLFORM_END); curl_formadd(&post, &last, CURLFORM_COPYNAME, "notify", CURLFORM_COPYCONTENTS, "on", CURLFORM_END); @@ -466,7 +535,7 @@ } else { long response_code; curl_easy_getinfo(clam_curl, CURLINFO_RESPONSE_CODE, &response_code); - if (response_code/100 == 3) { + if (response_code / 100 == 3) { curl_easy_getinfo(clam_curl, CURLINFO_REDIRECT_URL, &urlp); if (urlp == NULL) { fprintf(stderr, "POST submit Location URL is NULL.\n"); @@ -475,25 +544,21 @@ sp = strstr(urlp, "/reports/"); if (sp == NULL) { fprintf(stderr, "POST submit Location URL is malformed.\n"); - } - else if (!strcmp(sp, "/reports/success")) { + } else if (!strcmp(sp, "/reports/success")) { fprintf(stdout, "Submission success!\n"); status = 0; - } - else if (!strcmp(sp, "/reports/failure")) { + } else if (!strcmp(sp, "/reports/failure")) { fprintf(stdout, "Submission failed\n"); - } - else { + } else { fprintf(stdout, "Unknown submission status %s\n", sp); } - } - else { + } else { fprintf(stderr, "Unexpected POST submit response code: %li\n", response_code); } } cleanup: - /* + /* * Cleanup */ if (slist != NULL) { @@ -529,7 +594,7 @@ } if (submissionID != NULL) { free(submissionID); - } + } if (authenticity_token != NULL) { free(authenticity_token); } @@ -541,7 +606,6 @@ return status; } - char *read_stream(void) { char *filename; @@ -562,7 +626,7 @@ while (!feof(stdin)) { nwritten = 0; - nread = fread(buf, 1, sizeof(buf), stdin); + nread = fread(buf, 1, sizeof(buf), stdin); if (nread == 0) { fclose(fp); remove(filename); diff -Nru clamav-0.101.4+dfsg/config/ar-lib clamav-0.102.1+dfsg/config/ar-lib --- clamav-0.101.4+dfsg/config/ar-lib 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/ar-lib 2019-11-20 04:42:24.000000000 +0000 @@ -4,7 +4,7 @@ me=ar-lib scriptversion=2012-03-01.08; # UTC -# Copyright (C) 2010-2013 Free Software Foundation, Inc. +# Copyright (C) 2010-2017 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify diff -Nru clamav-0.101.4+dfsg/config/compile clamav-0.102.1+dfsg/config/compile --- clamav-0.101.4+dfsg/config/compile 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/compile 2019-11-20 04:42:24.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2012-10-14.11; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify diff -Nru clamav-0.101.4+dfsg/config/config.guess clamav-0.102.1+dfsg/config/config.guess --- clamav-0.101.4+dfsg/config/config.guess 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/config.guess 2019-11-20 04:42:24.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2013-06-10' +timestamp='2018-02-24' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -24,12 +24,12 @@ # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # -# Originally written by Per Bothner. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` @@ -39,7 +39,7 @@ Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -107,9 +107,9 @@ dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -132,14 +132,14 @@ UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -case "${UNAME_SYSTEM}" in +case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu - eval $set_cc_for_build - cat <<-EOF > $dummy.c + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc @@ -149,13 +149,20 @@ LIBC=gnu #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi ;; esac # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, @@ -168,21 +175,31 @@ # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then @@ -197,44 +214,67 @@ os=netbsd ;; esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -251,63 +291,54 @@ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -319,7 +350,7 @@ echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos @@ -346,38 +377,38 @@ sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) - echo i386-pc-auroraux${UNAME_RELEASE} + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + eval "$set_cc_for_build" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -386,25 +417,25 @@ ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -415,44 +446,44 @@ # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} + echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} + echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} + echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -461,23 +492,23 @@ #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -503,17 +534,17 @@ AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) @@ -530,7 +561,7 @@ echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -542,14 +573,14 @@ if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -560,7 +591,7 @@ exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -574,26 +605,27 @@ exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -608,28 +640,28 @@ echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include @@ -662,13 +694,13 @@ exit (0); } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -679,23 +711,23 @@ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -720,11 +752,11 @@ exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -733,7 +765,7 @@ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -741,9 +773,9 @@ exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -768,127 +800,109 @@ echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` - case ${UNAME_PROCESSOR} in + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) - echo ${UNAME_MACHINE}-pc-mingw64 + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 - exit ;; - i*:MSYS*:*) - echo ${UNAME_MACHINE}-pc-msys + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) - case ${UNAME_MACHINE} in + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) - echo x86_64-unknown-interix${UNAME_RELEASE} + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - 8664:Windows_NT:*) - echo x86_64-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -901,58 +915,64 @@ EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="gnulibc1" ; fi - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else - echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-${LIBC} + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) - echo ${UNAME_MACHINE}-pc-linux-${LIBC} + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el @@ -966,64 +986,74 @@ #endif #endif EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } ;; - or1k:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-${LIBC} + echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-${LIBC} + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; - PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; - *) echo hppa-unknown-linux-${LIBC} ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-${LIBC} + echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-${LIBC} + echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) - echo powerpc64le-unknown-linux-${LIBC} + echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) - echo powerpcle-unknown-linux-${LIBC} + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-${LIBC} + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + if objdump -f /bin/sh | grep -q elf32-x86-64; then + echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32 + else + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + fi exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1037,34 +1067,34 @@ # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) @@ -1074,12 +1104,12 @@ *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1089,9 +1119,9 @@ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) @@ -1099,7 +1129,7 @@ # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; @@ -1111,9 +1141,9 @@ exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1133,9 +1163,9 @@ test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; @@ -1144,28 +1174,28 @@ test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1176,7 +1206,7 @@ *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi @@ -1196,23 +1226,23 @@ exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. @@ -1231,67 +1261,93 @@ echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build + eval "$set_cc_for_build" if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - case $UNAME_PROCESSOR in - i386) UNAME_PROCESSOR=x86_64 ;; - powerpc) UNAME_PROCESSOR=powerpc64 ;; - esac + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 fi - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NEO-?:NONSTOP_KERNEL:*:*) - echo neo-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1300,18 +1356,18 @@ echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1332,14 +1388,14 @@ echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1348,182 +1404,48 @@ echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) - echo ${UNAME_MACHINE}-unknown-esx + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs exit ;; esac -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#endif - -#if defined (NeXT) -#if !defined (__ARCHITECTURE__) -#define __ARCHITECTURE__ "m68k" -#endif - int version; - version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif +echo "$0: unable to guess system type" >&2 -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 </dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi + ;; +esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1542,16 +1464,16 @@ /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff -Nru clamav-0.101.4+dfsg/config/config.sub clamav-0.102.1+dfsg/config/config.sub --- clamav-0.101.4+dfsg/config/config.sub 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/config.sub 2019-11-20 04:42:24.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2013 Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2013-08-10' +timestamp='2018-02-22' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -15,7 +15,7 @@ # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see . +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -25,7 +25,7 @@ # of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches with a ChangeLog entry to config-patches@gnu.org. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -33,7 +33,7 @@ # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: -# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases @@ -53,12 +53,11 @@ me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -68,7 +67,7 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2013 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -95,7 +94,7 @@ *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -113,24 +112,24 @@ # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -179,44 +178,44 @@ ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 @@ -228,10 +227,7 @@ os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -255,16 +251,18 @@ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ + | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ @@ -282,8 +280,10 @@ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ @@ -295,14 +295,15 @@ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | open8 \ - | or1k | or32 \ - | pdp10 | pdp11 | pj | pjl \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ + | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -310,7 +311,8 @@ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ - | we32k \ + | visium \ + | wasm32 \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown @@ -324,11 +326,14 @@ c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown @@ -357,7 +362,7 @@ ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. @@ -369,18 +374,20 @@ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ @@ -400,8 +407,10 @@ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ @@ -413,16 +422,19 @@ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -430,6 +442,8 @@ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -443,7 +457,7 @@ # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -477,7 +491,7 @@ basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -506,6 +520,9 @@ basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -519,7 +536,7 @@ os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) @@ -527,13 +544,13 @@ os=-cnk ;; c54x-*) - basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c55x-*) - basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c6x-*) - basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray @@ -622,10 +639,18 @@ basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -715,9 +740,6 @@ hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -730,26 +752,26 @@ basic_machine=i370-ibm ;; i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -767,17 +789,17 @@ basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -809,10 +831,10 @@ os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -822,12 +844,16 @@ basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc @@ -869,7 +895,7 @@ basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -914,6 +940,12 @@ nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -946,7 +978,7 @@ os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -962,7 +994,7 @@ basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -977,16 +1009,16 @@ basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould @@ -996,23 +1028,23 @@ ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) - basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -1066,17 +1098,10 @@ sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1095,7 +1120,7 @@ os=-sysv4 ;; strongarm-* | thumb-*) - basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun @@ -1217,6 +1242,9 @@ basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1225,20 +1253,12 @@ basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) - basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1267,10 +1287,6 @@ vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1280,9 +1296,6 @@ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1302,7 +1315,7 @@ # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1310,10 +1323,10 @@ # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1324,8 +1337,8 @@ if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux @@ -1336,45 +1349,48 @@ -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1391,12 +1407,12 @@ -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1405,10 +1421,10 @@ os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition @@ -1419,12 +1435,6 @@ -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1449,7 +1459,7 @@ -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1471,7 +1481,7 @@ -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1486,32 +1496,38 @@ -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; -nacl*) ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1592,9 +1608,6 @@ mips*-*) os=-elf ;; - or1k-*) - os=-elf - ;; or32-*) os=-coff ;; @@ -1604,12 +1617,12 @@ sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; @@ -1649,7 +1662,7 @@ m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1664,9 +1677,6 @@ i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1776,15 +1786,15 @@ vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'write-file-functions 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff -Nru clamav-0.101.4+dfsg/config/depcomp clamav-0.102.1+dfsg/config/depcomp --- clamav-0.101.4+dfsg/config/depcomp 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/depcomp 2019-11-20 04:42:24.000000000 +0000 @@ -1,9 +1,9 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2013-05-30.07; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1999-2013 Free Software Foundation, Inc. +# Copyright (C) 1999-2017 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -786,6 +786,6 @@ # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru clamav-0.101.4+dfsg/config/install-sh clamav-0.102.1+dfsg/config/install-sh --- clamav-0.101.4+dfsg/config/install-sh 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/install-sh 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2011-11-20.07; # UTC +scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -41,19 +41,15 @@ # This script is compatible with the BSD install script, but was written # from scratch. +tab=' ' nl=' ' -IFS=" "" $nl" +IFS=" $tab$nl" -# set DOITPROG to echo to test this script +# Set DOITPROG to "echo" to test this script. -# Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} -if test -z "$doit"; then - doit_exec=exec -else - doit_exec=$doit -fi +doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. @@ -68,17 +64,6 @@ rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} -posix_glob='?' -initialize_posix_glob=' - test "$posix_glob" != "?" || { - if (set -f) 2>/dev/null; then - posix_glob= - else - posix_glob=: - fi - } -' - posix_mkdir= # Desired mode of installed file. @@ -97,7 +82,7 @@ dst_arg= copy_on_change=false -no_target_directory= +is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE @@ -137,46 +122,57 @@ -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" - shift;; + shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 - case $mode in - *' '* | *' '* | *' -'* | *'*'* | *'?'* | *'['*) - echo "$0: invalid mode: $mode" >&2 - exit 1;; - esac - shift;; + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; -o) chowncmd="$chownprog $2" - shift;; + shift;; -s) stripcmd=$stripprog;; - -t) dst_arg=$2 - # Protect names problematic for 'test' and other utilities. - case $dst_arg in - -* | [=\(\)!]) dst_arg=./$dst_arg;; - esac - shift;; + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; - -T) no_target_directory=true;; + -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; - --) shift - break;; + --) shift + break;; - -*) echo "$0: invalid option: $1" >&2 - exit 1;; + -*) echo "$0: invalid option: $1" >&2 + exit 1;; *) break;; esac shift done +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. @@ -208,6 +204,15 @@ fi if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 @@ -223,16 +228,16 @@ *[0-7]) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw='% 200' + u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then - u_plus_rw= + u_plus_rw= else - u_plus_rw=,u+rw + u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac @@ -269,41 +274,15 @@ # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dst_arg: Is a directory" >&2 - exit 1 + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else - # Prefer dirname, but fall back on a substitute if dirname fails. - dstdir=` - (dirname "$dst") 2>/dev/null || - expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$dst" : 'X\(//\)[^/]' \| \ - X"$dst" : 'X\(//\)$' \| \ - X"$dst" : 'X\(/\)' \| . 2>/dev/null || - echo X"$dst" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q' - ` - + dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi @@ -314,74 +293,81 @@ if test $dstdir_status != 0; then case $posix_mkdir in '') - # Create intermediate dirs using mode 755 as modified by the umask. - # This is like FreeBSD 'install' as of 1997-10-28. - umask=`umask` - case $stripcmd.$umask in - # Optimize common cases. - *[2367][2367]) mkdir_umask=$umask;; - .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; - - *[0-7]) - mkdir_umask=`expr $umask + 22 \ - - $umask % 100 % 40 + $umask % 20 \ - - $umask % 10 % 4 + $umask % 2 - `;; - *) mkdir_umask=$umask,go-w;; - esac - - # With -d, create the new directory with the user-specified mode. - # Otherwise, rely on $mkdir_umask. - if test -n "$dir_arg"; then - mkdir_mode=-m$mode - else - mkdir_mode= - fi - - posix_mkdir=false - case $umask in - *[123567][0-7][0-7]) - # POSIX mkdir -p sets u+wx bits regardless of umask, which - # is incompatible with FreeBSD 'install' when (umask & 300) != 0. - ;; - *) - tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 - - if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 - then - if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. - # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or - # other-writable bit of parent directory when it shouldn't. - # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` - case $ls_ld_tmpdir in - d????-?r-*) different_mode=700;; - d????-?--*) different_mode=755;; - *) false;; - esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` - test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" - } - } - then posix_mkdir=: - fi - rmdir "$tmpdir/d" "$tmpdir" - else - # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null - fi - trap '' 0;; - esac;; + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. + if (umask $mkdir_umask && + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null + fi + trap '' 0;; + esac;; esac if $posix_mkdir && ( - umask $mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else @@ -391,53 +377,51 @@ # directory the slow way, step by step, checking for races as we go. case $dstdir in - /*) prefix='/';; - [-=\(\)!]*) prefix='./';; - *) prefix='';; + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; esac - eval "$initialize_posix_glob" - oIFS=$IFS IFS=/ - $posix_glob set -f + set -f set fnord $dstdir shift - $posix_glob set +f + set +f IFS=$oIFS prefixes= for d do - test X"$d" = X && continue + test X"$d" = X && continue - prefix=$prefix$d - if test -d "$prefix"; then - prefixes= - else - if $posix_mkdir; then - (umask=$mkdir_umask && - $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break - # Don't fail if two instances are running concurrently. - test -d "$prefix" || exit 1 - else - case $prefix in - *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; - *) qprefix=$prefix;; - esac - prefixes="$prefixes '$qprefix'" - fi - fi - prefix=$prefix/ + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ done if test -n "$prefixes"; then - # Don't fail if two instances are running concurrently. - (umask $mkdir_umask && - eval "\$doit_exec \$mkdirprog $prefixes") || - test -d "$dstdir" || exit 1 - obsolete_mkdir_used=true + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true fi fi fi @@ -472,15 +456,12 @@ # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && - old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && - new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && - - eval "$initialize_posix_glob" && - $posix_glob set -f && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && - $posix_glob set +f && - + set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then @@ -493,24 +474,24 @@ # to itself, or perhaps because mv is so ancient that it does not # support -f. { - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - test ! -f "$dst" || - $doit $rmcmd -f "$dst" 2>/dev/null || - { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && - { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } - } || - { echo "$0: cannot unlink or rename $dst" >&2 - (exit 1); exit 1 - } - } && + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dst" + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 diff -Nru clamav-0.101.4+dfsg/config/ltmain.sh clamav-0.102.1+dfsg/config/ltmain.sh --- clamav-0.101.4+dfsg/config/ltmain.sh 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/ltmain.sh 2019-11-20 04:42:24.000000000 +0000 @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION=2.4.6 +VERSION="2.4.6 Debian-2.4.6-2" package_revision=2.4.6 @@ -2068,12 +2068,12 @@ compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) - version: $progname (GNU libtool) 2.4.6 + version: $progname $scriptversion Debian-2.4.6-2 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . -GNU libtool home page: . +GNU libtool home page: . General help using GNU software: ." exit 0 } @@ -7272,10 +7272,13 @@ # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" @@ -7568,7 +7571,10 @@ case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then @@ -7887,19 +7893,19 @@ # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done continue fi # $pass = conv @@ -8823,6 +8829,9 @@ revision=$number_minor lt_irix_increment=no ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; esac ;; no) diff -Nru clamav-0.101.4+dfsg/config/missing clamav-0.102.1+dfsg/config/missing --- clamav-0.101.4+dfsg/config/missing 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/missing 2019-11-20 04:42:24.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2013-10-28.13; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify diff -Nru clamav-0.101.4+dfsg/config/test-driver clamav-0.102.1+dfsg/config/test-driver --- clamav-0.101.4+dfsg/config/test-driver 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/test-driver 2019-11-20 04:42:24.000000000 +0000 @@ -3,7 +3,7 @@ scriptversion=2013-07-13.22; # UTC -# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -106,11 +106,14 @@ # Test script is run here. "$@" >$log_file 2>&1 estatus=$? + if test $enable_hard_errors = no && test $estatus -eq 99; then - estatus=1 + tweaked_estatus=1 +else + tweaked_estatus=$estatus fi -case $estatus:$expect_failure in +case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; @@ -119,6 +122,12 @@ *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac +# Report the test outcome and exit status in the logs, so that one can +# know whether the test passed or failed simply by looking at the '.log' +# file, without the need of also peaking into the corresponding '.trs' +# file (automake bug#11814). +echo "$res $test_name (exit status: $estatus)" >>$log_file + # Report outcome to console. echo "${col}${res}${std}: $test_name" diff -Nru clamav-0.101.4+dfsg/config/ylwrap clamav-0.102.1+dfsg/config/ylwrap --- clamav-0.101.4+dfsg/config/ylwrap 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/config/ylwrap 2019-11-20 04:42:24.000000000 +0000 @@ -1,9 +1,9 @@ #! /bin/sh # ylwrap - wrapper for lex/yacc invocations. -scriptversion=2013-01-12.17; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # # Written by Tom Tromey . # @@ -242,6 +242,6 @@ # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: diff -Nru clamav-0.101.4+dfsg/configure clamav-0.102.1+dfsg/configure --- clamav-0.101.4+dfsg/configure 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/configure 2019-11-20 04:42:24.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for ClamAV 0.101.4. +# Generated by GNU Autoconf 2.69 for ClamAV 0.102.1. # # Report bugs to . # @@ -592,8 +592,8 @@ # Identity of this package. PACKAGE_NAME='ClamAV' PACKAGE_TARNAME='clamav' -PACKAGE_VERSION='0.101.4' -PACKAGE_STRING='ClamAV 0.101.4' +PACKAGE_VERSION='0.102.1' +PACKAGE_STRING='ClamAV 0.102.1' PACKAGE_BUGREPORT='https://bugzilla.clamav.net/' PACKAGE_URL='https://www.clamav.net/' @@ -636,7 +636,9 @@ ac_func_list= enable_option_checking=no -ac_subst_vars='ENABLE_YARA_FALSE +ac_subst_vars='ENABLE_CLAMSUBMIT_FALSE +ENABLE_CLAMSUBMIT_TRUE +ENABLE_YARA_FALSE ENABLE_YARA_TRUE ENABLE_LLVM_FALSE ENABLE_LLVM_TRUE @@ -658,7 +660,21 @@ UINT8_DEF INT8_DEF GENERATE_WARNING +MACOS_FALSE +MACOS_TRUE +WINDOWS_FALSE +WINDOWS_TRUE +LINUX_FALSE +LINUX_TRUE +am__fastdepOBJC_FALSE +am__fastdepOBJC_TRUE +OBJCDEPMODE +ac_ct_OBJC +OBJCFLAGS +OBJC HAVE_STRNI +CURL_LDFLAGS +CURL_LIBS JSON_LDFLAGS JSON_LIBS SSL_LDFLAGS @@ -669,6 +685,7 @@ CLAMDTOP_LIBS THREAD_LIBS TH_SAFE +CLAMONACC_LIBS CLAMDSCAN_LIBS CLAMSCAN_LIBS FRESHCLAM_LIBS @@ -678,6 +695,7 @@ LIBCLAMAV_LIBS PCRE_CPPFLAGS JSON_CPPFLAGS +CURL_CPPFLAGS SSL_CPPFLAGS LIBCLAMSHARED_CPPFLAGS CLAMBC_CPPFLAGS @@ -688,11 +706,13 @@ CLAMAV_MILTER_CPPFLAGS CLAMMEM_CPPFLAGS CLAMD_CPPFLAGS +CLAMONACC_CPPFLAGS CLAMDSCAN_CPPFLAGS CLAMSCAN_CPPFLAGS FRESHCLAM_CPPFLAGS CLAMSUBMIT_CFLAGS CLAMSUBMIT_LIBS +curl_config LIBPRELUDE_CONFIG_PREFIX LIBPRELUDE_PREFIX LIBPRELUDE_LIBS @@ -700,10 +720,6 @@ LIBPRELUDE_PTHREAD_CFLAGS LIBPRELUDE_CFLAGS LIBPRELUDE_CONFIG -ENABLE_LIBFRESHCLAM_FALSE -ENABLE_LIBFRESHCLAM_TRUE -ENABLE_CLAMSUBMIT_FALSE -ENABLE_CLAMSUBMIT_TRUE SYSTEM_LFS_FTS_FALSE SYSTEM_LFS_FTS_TRUE HAVE_YARA @@ -724,8 +740,8 @@ BUILD_CLAMD_TRUE CFGDIR DBDIR -ICONV_CPPFLAGS -ICONV_LDFLAGS +LTLIBICONV +LIBICONV INSTALL_SYSTEMD_UNITS_FALSE INSTALL_SYSTEMD_UNITS_TRUE systemdsystemunitdir @@ -738,6 +754,8 @@ LIBBZ2_PREFIX LTLIBBZ2 LIBBZ2 +ZLIB_LIBS +ZLIB_CFLAGS MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE @@ -750,6 +768,7 @@ HAVE_LIBXML2_TRUE XML_LIBS XML_CPPFLAGS +xmlconfig ENABLE_COVERAGE_FALSE ENABLE_COVERAGE_TRUE GENHTML @@ -773,6 +792,10 @@ LEXLIB LEX_OUTPUT_ROOT LEX +BUILD_CLAMONACC_FALSE +BUILD_CLAMONACC_TRUE +BUILD_LIBCLAMAV_ONLY_FALSE +BUILD_LIBCLAMAV_ONLY_TRUE PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG @@ -813,7 +836,11 @@ FGREP SED LIBTOOL +LIBFRESHCLAM_VERSION_NUM +LIBFRESHCLAM_VERSION +LIBCLAMAV_VERSION_NUM LIBCLAMAV_VERSION +PACKAGE_VERSION_NUM EGREP GREP CPP @@ -900,6 +927,7 @@ docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -922,6 +950,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking +enable_mmap_for_cross_compiling enable_dependency_tracking enable_silent_rules enable_static @@ -936,6 +965,7 @@ with_ltdl_include with_ltdl_lib enable_ltdl_install +enable_libclamav_only enable_gcc_vcheck enable_experimental enable_fuzz @@ -948,11 +978,11 @@ with_xml with_openssl with_libjson +with_libjson_static with_pcre with_system_libmspack enable_maintainer_mode with_zlib -enable_zlib_vcheck enable_bzip2 with_libbz2_prefix enable_unrar @@ -962,7 +992,7 @@ enable_dns enable_fanotify enable_milter -with_iconv +with_libiconv_prefix enable_pthreads enable_cr enable_id_check @@ -974,7 +1004,6 @@ enable_dns_fix enable_bigstack with_dbdir -enable_readdir_r enable_fdpassing enable_clamdtop with_libncurses_prefix @@ -985,9 +1014,9 @@ with_llvm_linking enable_sha_collector_for_internal_use enable_yara -enable_libfreshclam enable_prelude with_libprelude_prefix +enable_clamonacc with_libcurl enable_strni enable_largefile @@ -1015,8 +1044,12 @@ CHECK_LIBS LIBMSPACK_CFLAGS LIBMSPACK_LIBS +ZLIB_CFLAGS +ZLIB_LIBS SYSTEMD_CFLAGS -SYSTEMD_LIBS' +SYSTEMD_LIBS +OBJC +OBJCFLAGS' ac_subdirs_all=' libclamav/c++' @@ -1056,6 +1089,7 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1308,6 +1342,15 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1445,7 +1488,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1558,7 +1601,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ClamAV 0.101.4 to adapt to many kinds of systems. +\`configure' configures ClamAV 0.102.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1598,6 +1641,7 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1624,19 +1668,23 @@ --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-mmap-for-cross-compiling + set to "yes" to force enable mmap support without + checking under cross-compiling. This could help + enable mempool feature. _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ClamAV 0.101.4:";; + short | recursive ) echo "Configuration of ClamAV 0.102.1:";; esac cat <<\_ACEOF - -Optional Features: - --disable-option-checking ignore unrecognized --enable/--with options - --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) - --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking @@ -1649,6 +1697,8 @@ optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-ltdl-install install libltdl + --enable-libclamav-only build libclamav library and dependencies + [default=no] --disable-gcc-vcheck do not check for buggy gcc version --enable-experimental enable experimental code --enable-fuzz enable building standalone fuzz targets [default=no] @@ -1660,7 +1710,6 @@ --enable-maintainer-mode make rules and dependencies not useful (and sometimes confusing) to the casual installer - --disable-zlib-vcheck do not check for buggy zlib version --disable-bzip2 do not include bzip2 support --disable-unrar do not build libclamunrar and libclamunrar_iface --disable-getaddrinfo do not include support for getaddrinfo @@ -1677,7 +1726,6 @@ --enable-dns-fix enable workaround for broken DNS servers (as in SpeedTouch 510) --enable-bigstack increase thread stack size - --enable-readdir_r enable support for readdir_r --disable-fdpassing do not build file descriptor passing support --enable-clamdtop build clamdtop tool [default=auto] --enable-distcheck-werror @@ -1685,8 +1733,8 @@ --enable-llvm enable 'llvm' JIT/verifier support [default=auto] --disable-yara do not include yara support - --enable-libfreshclam enable building of libfreshclam --enable-prelude Enable Prelude support for alerts. + --enable-clamonacc build clamonacc tool [default=auto] --enable-strni enables explicit use of internal strn functions to support cross-compilation against older libs --disable-largefile omit support for large files @@ -1717,20 +1765,25 @@ --with-libjson[=DIR] path to directory containing libjson [default=/usr/local or /usr if not found in /usr/local] + --with-libjson-static=DIR + path to libjson-c.a static library --with-pcre[=DIR] path to directory containing libpcre library, prioritizes PCRE2 over PCRE [default=search PATH environment variable] --with-system-libmspack Specify system libmspack location or to use internal package, uses full path to libmspack or bin directory (default=search PATH environment variable) - --with-zlib[=DIR] path to directory containing zlib library + + --with-zlib[=DIR] path to directory containing zlib library [default=/usr/local or /usr if not found in /usr/local] + --with-libbz2-prefix[=DIR] search for libbz2 in DIR/include and DIR/lib --without-libbz2-prefix don't search for libbz2 in includedir and libdir --with-systemdsystemunitdir=DIR Directory for systemd service files - --with-iconv supports iconv() [default=auto] + --with-libiconv-prefix[=DIR] search for libiconv in DIR/include and DIR/lib + --without-libiconv-prefix don't search for libiconv in includedir and libdir --with-user[=uid] name of the clamav user [default=clamav] --with-group[=gid] name of the clamav group [default=clamav] --with-version[=STR] use custom version string (dev only) @@ -1782,10 +1835,14 @@ C compiler flags for LIBMSPACK, overriding pkg-config LIBMSPACK_LIBS linker flags for LIBMSPACK, overriding pkg-config + ZLIB_CFLAGS C compiler flags for ZLIB, overriding pkg-config + ZLIB_LIBS linker flags for ZLIB, overriding pkg-config SYSTEMD_CFLAGS C compiler flags for SYSTEMD, overriding pkg-config SYSTEMD_LIBS linker flags for SYSTEMD, overriding pkg-config + OBJC Objective C compiler command + OBJCFLAGS Objective C compiler flags Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1854,7 +1911,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ClamAV configure 0.101.4 +ClamAV configure 0.102.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2440,11 +2497,49 @@ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type + +# ac_fn_objc_try_compile LINENO +# ----------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_objc_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_objc_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_objc_try_compile cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ClamAV $as_me 0.101.4, which was +It was created by ClamAV $as_me 0.102.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2809,6 +2904,65 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu +ac_aux_dir= +for ac_dir in config "$srcdir"/config; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + + +ac_aux_dir= +for ac_dir in config "$srcdir"/config; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' @@ -3319,35 +3473,6 @@ -ac_aux_dir= -for ac_dir in config "$srcdir"/config; do - if test -f "$ac_dir/install-sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f "$ac_dir/install.sh"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - elif test -f "$ac_dir/shtool"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/shtool install -c" - break - fi -done -if test -z "$ac_aux_dir"; then - as_fn_error $? "cannot find install-sh, install.sh, or shtool in config \"$srcdir\"/config" "$LINENO" 5 -fi - -# These three variables are undocumented and unsupported, -# and are intended to be withdrawn in a future Autoconf release. -# They can cause serious problems if a builder's source tree is in a directory -# whose full name contains unusual characters. -ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. -ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. -ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. - - ac_config_headers="$ac_config_headers clamav-config.h libclammspack/config.h:libclammspack/config.h.in" @@ -3652,7 +3777,7 @@ -am__api_version='1.14' +am__api_version='1.15' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or @@ -3824,8 +3949,8 @@ ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -3844,7 +3969,7 @@ $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -4201,7 +4326,7 @@ # Define the identity of the package. PACKAGE='clamav' - VERSION='0.101.4' + VERSION='0.102.1' # Some tools Automake needs. @@ -4226,8 +4351,8 @@ # mkdir_p='$(MKDIR_P)' -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' @@ -4528,6 +4653,7 @@ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi + # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; @@ -5929,25 +6055,54 @@ -VERSION="0.101.4" +VERSION="0.102.1" + +major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/^0-9//g"` +minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/^0-9//g"` +patch=`echo $PACKAGE_VERSION |cut -d. -f3 | cut -d- -f1 | sed -e "s/^0-9//g"` + +PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"` + LC_CURRENT=9 -LC_REVISION=2 +LC_REVISION=4 LC_AGE=0 LIBCLAMAV_VERSION="$LC_CURRENT":"$LC_REVISION":"$LC_AGE" -major=`expr $LC_CURRENT - $LC_AGE` +LIBCLAMAV_VERSION_NUM=`printf "0x%02x%02x%02x" "$LC_CURRENT" "$LC_REVISION" "$LC_AGE"` + + +LC_MAJOR=`expr $LC_CURRENT - $LC_AGE` + +cat >>confdefs.h <<_ACEOF +#define LIBCLAMAV_FULLVER "$LC_MAJOR.$LC_AGE.$LC_REVISION" +_ACEOF cat >>confdefs.h <<_ACEOF -#define LIBCLAMAV_FULLVER "$major.$LC_AGE.$LC_REVISION" +#define LIBCLAMAV_MAJORVER $LC_MAJOR _ACEOF +LFC_CURRENT=2 +LFC_REVISION=0 +LFC_AGE=0 +LIBFRESHCLAM_VERSION="$LFC_CURRENT":"$LFC_REVISION":"$LFC_AGE" + + +LIBFRESHCLAM_VERSION_NUM=`printf "0x%02x%02x%02x" "$LFC_CURRENT" "$LFC_REVISION" "$LFC_AGE"` + + +LFC_MAJOR=`expr $LFC_CURRENT - $LFC_AGE` cat >>confdefs.h <<_ACEOF -#define LIBCLAMAV_MAJORVER $major +#define LIBFRESHCLAM_FULLVER "$LFC_MAJOR.$LFC_AGE.$LFC_REVISION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define LIBFRESHCLAM_MAJORVER $LFC_MAJOR _ACEOF @@ -7078,7 +7233,7 @@ lt_cv_deplibs_check_method=pass_all ;; -netbsd*) +netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else @@ -10512,6 +10667,9 @@ openbsd* | bitrig*) with_gnu_ld=no ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; esac ld_shlibs=yes @@ -10766,7 +10924,7 @@ fi ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -11436,6 +11594,7 @@ if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi + link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -11457,7 +11616,7 @@ esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -12572,6 +12731,18 @@ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -15466,7 +15637,7 @@ ;; esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -15841,6 +16012,9 @@ ;; esac ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs_CXX=no + ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; @@ -16534,6 +16708,18 @@ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -17498,7 +17684,7 @@ # at 6.2 and later dlopen does load deplibs. lt_cv_sys_dlopen_deplibs=yes ;; - netbsd*) + netbsd* | netbsdelf*-gnu) lt_cv_sys_dlopen_deplibs=yes ;; openbsd*) @@ -18078,6 +18264,35 @@ fi fi +# Check whether --enable-libclamav-only was given. +if test "${enable_libclamav_only+set}" = set; then : + enableval=$enable_libclamav_only; enable_libclamav_only=$enableval +else + enable_libclamav_only="no" +fi + + + if test x$enable_libclamav_only == xyes; then + BUILD_LIBCLAMAV_ONLY_TRUE= + BUILD_LIBCLAMAV_ONLY_FALSE='#' +else + BUILD_LIBCLAMAV_ONLY_TRUE='#' + BUILD_LIBCLAMAV_ONLY_FALSE= +fi + + +if test "$enable_libclamav_only" == "yes"; then + if test x$enable_libclamav_only == xno; then + BUILD_CLAMONACC_TRUE= + BUILD_CLAMONACC_FALSE='#' +else + BUILD_CLAMONACC_TRUE='#' + BUILD_CLAMONACC_FALSE= +fi + +fi + + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -20633,7 +20848,13 @@ else if test "$cross_compiling" = yes; then : + + if test $enable_mmap_for_cross_compiling = yes; then + ac_cv_c_mmap_private=yes + else ac_cv_c_mmap_private=no + fi + else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21902,6 +22123,7 @@ XML_HOME="" +xmlconfig="" if test "X$want_xml" != "Xno"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libxml2 installation" >&5 $as_echo_n "checking for libxml2 installation... " >&6; } @@ -21912,9 +22134,8 @@ fi -fi -if test "x$with_xml_val" = "xno"; then : + if test "x$with_xml_val" = "xno"; then : XML_HOME="" elif test "x$with_xml_val" = "xyes"; then : XML_HOME="/usr/local" @@ -21922,72 +22143,134 @@ XML_HOME="$with_xml_val" fi -if test "x$XML_HOME" != "x"; then : + if test "x$XML_HOME" != "x"; then : - if test ! -x "$XML_HOME/bin/xml2-config"; then : + if test ! -x "$XML_HOME/bin/xml2-config"; then : XML_HOME="" fi fi -if test "x$XML_HOME" = "x" -a "x$with_xml_val" = "xyes"; then : + if test "x$XML_HOME" = "x" -a "x$with_xml_val" = "xyes"; then : - if test -x "/usr/bin/xml2-config"; then : + if test -x "/usr/bin/xml2-config"; then : XML_HOME="/usr" fi fi -if test "x$XML_HOME" != "x"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML_HOME" >&5 + if test "x$XML_HOME" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML_HOME" >&5 $as_echo "$XML_HOME" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 + with_xml="yes" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } + fi + + found_xml="no" + XMLCONF_VERSION="" + XML_CPPFLAGS="" + XML_LIBS="" + case "$with_xml" in + yes) # Extract the first word of "xml2-config", so it can be a program name with args. +set dummy xml2-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_xmlconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $xmlconfig in + [\\/]* | ?:[\\/]*) + ac_cv_path_xmlconfig="$xmlconfig" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_xmlconfig="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +xmlconfig=$ac_cv_path_xmlconfig +if test -n "$xmlconfig"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xmlconfig" >&5 +$as_echo "$xmlconfig" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } fi -found_xml="no" -XMLCONF_VERSION="" -XML_CPPFLAGS="" -XML_LIBS="" -if test "x$XML_HOME" != "x"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking xml2-config version" >&5 + + if test "x$xmlconfig" = x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: can not locate xml2-config in PATH, will search default XML_HOME variants" >&5 +$as_echo "$as_me: can not locate xml2-config in PATH, will search default XML_HOME variants" >&6;} + + if test "x$XML_HOME" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking xml2-config version" >&5 $as_echo_n "checking xml2-config version... " >&6; } - XMLCONF_VERSION="`$XML_HOME/bin/xml2-config --version`" - if test "x%XMLCONF_VERSION" != "x"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XMLCONF_VERSION" >&5 + XMLCONF_VERSION="`$XML_HOME/bin/xml2-config --version`" + + if test "x%XMLCONF_VERSION" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XMLCONF_VERSION" >&5 $as_echo "$XMLCONF_VERSION" >&6; } - found_xml="yes" - XML_CPPFLAGS="`$XML_HOME/bin/xml2-config --cflags`" - XML_LIBS="`$XML_HOME/bin/xml2-config --libs`" - $as_echo "$XML_CPPFLAGS" - $as_echo "$XML_LIBS" - else - as_fn_error $? "xml2-config failed" "$LINENO" 5 - fi -fi + found_xml="yes" + XML_CPPFLAGS="`$XML_HOME/bin/xml2-config --cflags`" + XML_LIBS="`$XML_HOME/bin/xml2-config --libs`" + $as_echo "$XML_CPPFLAGS" + $as_echo "$XML_LIBS" + else + as_fn_error $? "xml2-config failed" "$LINENO" 5 + fi + fi + else + found_xml="yes" + XMLCONF_VERSION="`$xmlconfig --version`" + XML_CPPFLAGS="`$xmlconfig --cflags`" + XML_LIBS="`$xmlconfig --libs`" + fi + esac -working_xml="no" -if test "X$found_xml" != "Xno"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlreader.h in $XML_HOME" >&5 -$as_echo_n "checking for xmlreader.h in $XML_HOME... " >&6; } + working_xml="no" + if test "X$found_xml" != "Xno"; then - if test ! -f "$XML_HOME/include/libxml2/libxml/xmlreader.h"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 + readerresult="" + if test "x$xmlconfig" = x ; then + readerresult="$XML_HOME/include/libxml2/libxml/xmlreader.h" + else + readerresult="`$xmlconfig --prefix`/include/libxml2/libxml/xmlreader.h" + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlreader.h in $readerresult" >&5 +$as_echo_n "checking for xmlreader.h in $readerresult... " >&6; } + + if test ! -f "$readerresult"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 $as_echo "found" >&6; } - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $XML_LIBS" + save_LIBS="$LIBS" + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $XML_CPPFLAGS" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $XML_LIBS" - $as_echo "CPPFLAGS: $CPPFLAGS" - $as_echo "LD_FLAGS: $LDFLAGS" + $as_echo "CPPFLAGS: $CPPFLAGS" + $as_echo "LD_FLAGS: $LDFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlTextReaderRead in -lxml2" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlTextReaderRead in -lxml2" >&5 $as_echo_n "checking for xmlTextReaderRead in -lxml2... " >&6; } if ${ac_cv_lib_xml2_xmlTextReaderRead+:} false; then : $as_echo_n "(cached) " >&6 @@ -22030,33 +22313,32 @@ fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + fi fi -fi -if test "$working_xml" = "yes"; then + if test "$working_xml" = "yes"; then $as_echo "#define HAVE_LIBXML2 1" >>confdefs.h - { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling and linking with libxml2 from $XML_HOME" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling and linking with libxml2 from $XML_HOME" >&5 $as_echo "$as_me: Compiling and linking with libxml2 from $XML_HOME" >&6;} -else - if test "$want_xml" = "yes"; then - as_fn_error $? "****** Please install libxml2 packages!" "$LINENO" 5 else - if test "$want_xml" != "no"; then + if test "$want_xml" = "yes"; then + as_fn_error $? "****** Please install libxml2 packages!" "$LINENO" 5 + else { $as_echo "$as_me:${as_lineno-$LINENO}: ****** libxml2 support unavailable" >&5 $as_echo "$as_me: ****** libxml2 support unavailable" >&6;} fi - fi - XML_CPPFLAGS="" - XML_LIBS="" + XML_CPPFLAGS="" + XML_LIBS="" + fi fi if test "x$HAVE_LIBXML2" = "xyes"; then @@ -22241,20 +22523,21 @@ # Check whether --with-libjson was given. if test "${with_libjson+set}" = set; then : withval=$with_libjson; -find_json="no" -if test "X$withval" = "Xyes"; then - find_json="yes" -else - if test "X$withval" != "Xno"; then - if test -f "${withval}/include/json/json.h" -o -f "${withval}/include/json-c/json.h"; then - LIBJSON_HOME="$withval" - have_json_header="yes" + find_json="no" + if test "X$withval" = "Xyes"; then + find_json="yes" + else + if test "X$withval" != "Xno"; then + if test -f "${withval}/include/json/json.h" -o -f "${withval}/include/json-c/json.h"; then + LIBJSON_HOME="$withval" + have_json_header="yes" + fi + fi fi - fi -fi else find_json="yes" + fi @@ -22297,12 +22580,13 @@ CFLAGS="$CFLAGS $JSON_CPPFLAGS" fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing json_object_object_get_ex" >&5 -$as_echo_n "checking for library containing json_object_object_get_ex... " >&6; } -if ${ac_cv_search_json_object_object_get_ex+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_object_get_ex in -ljson-c" >&5 +$as_echo_n "checking for json_object_object_get_ex in -ljson-c... " >&6; } +if ${ac_cv_lib_json_c_json_object_object_get_ex+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljson-c $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22321,47 +22605,76 @@ return 0; } _ACEOF -for ac_lib in '' json-c json; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_json_object_object_get_ex=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_json_c_json_object_object_get_ex=yes +else + ac_cv_lib_json_c_json_object_object_get_ex=no fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_json_object_object_get_ex+:} false; then : - break + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -done -if ${ac_cv_search_json_object_object_get_ex+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_c_json_object_object_get_ex" >&5 +$as_echo "$ac_cv_lib_json_c_json_object_object_get_ex" >&6; } +if test "x$ac_cv_lib_json_c_json_object_object_get_ex" = xyes; then : + + have_json="yes" + have_deprecated_json="no" + json_libname="json-c" else - ac_cv_search_json_object_object_get_ex=no + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_object_get_ex in -ljson" >&5 +$as_echo_n "checking for json_object_object_get_ex in -ljson... " >&6; } +if ${ac_cv_lib_json_json_object_object_get_ex+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljson $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char json_object_object_get_ex (); +int +main () +{ +return json_object_object_get_ex (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_json_json_object_object_get_ex=yes +else + ac_cv_lib_json_json_object_object_get_ex=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_json_object_object_get_ex" >&5 -$as_echo "$ac_cv_search_json_object_object_get_ex" >&6; } -ac_res=$ac_cv_search_json_object_object_get_ex -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_json_object_object_get_ex" >&5 +$as_echo "$ac_cv_lib_json_json_object_object_get_ex" >&6; } +if test "x$ac_cv_lib_json_json_object_object_get_ex" = xyes; then : + + have_json="yes" + have_deprecated_json="no" + json_libname="json" - have_json="yes" - have_deprecated_json="no" else - have_json="no" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing json_object_object_get" >&5 -$as_echo_n "checking for library containing json_object_object_get... " >&6; } -if ${ac_cv_search_json_object_object_get+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_object_get in -ljson-c" >&5 +$as_echo_n "checking for json_object_object_get in -ljson-c... " >&6; } +if ${ac_cv_lib_json_c_json_object_object_get+:} false; then : $as_echo_n "(cached) " >&6 else - ac_func_search_save_LIBS=$LIBS + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljson-c $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -22380,42 +22693,85 @@ return 0; } _ACEOF -for ac_lib in '' json-c json; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if ac_fn_c_try_link "$LINENO"; then : - ac_cv_search_json_object_object_get=$ac_res +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_json_c_json_object_object_get=yes +else + ac_cv_lib_json_c_json_object_object_get=no fi rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_json_object_object_get+:} false; then : - break + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -done -if ${ac_cv_search_json_object_object_get+:} false; then : +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_c_json_object_object_get" >&5 +$as_echo "$ac_cv_lib_json_c_json_object_object_get" >&6; } +if test "x$ac_cv_lib_json_c_json_object_object_get" = xyes; then : + have_json="yes" + have_deprecated_json="yes" + json_libname="json-c" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for json_object_object_get in -ljson" >&5 +$as_echo_n "checking for json_object_object_get in -ljson... " >&6; } +if ${ac_cv_lib_json_json_object_object_get+:} false; then : + $as_echo_n "(cached) " >&6 else - ac_cv_search_json_object_object_get=no + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljson $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char json_object_object_get (); +int +main () +{ +return json_object_object_get (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_json_json_object_object_get=yes +else + ac_cv_lib_json_json_object_object_get=no fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_json_object_object_get" >&5 -$as_echo "$ac_cv_search_json_object_object_get" >&6; } -ac_res=$ac_cv_search_json_object_object_get -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_json_json_object_object_get" >&5 +$as_echo "$ac_cv_lib_json_json_object_object_get" >&6; } +if test "x$ac_cv_lib_json_json_object_object_get" = xyes; then : + + have_json="yes" + have_deprecated_json="yes" + json_libname="json" + +else + + have_json="no" + as_fn_error $? "Unable to find libjson library." "$LINENO" 5 - have_json="yes" - have_deprecated_json="yes" fi + +fi + + + +fi + + + fi @@ -22432,7 +22788,22 @@ $as_echo "#define HAVE_DEPRECATED_JSON 1" >>confdefs.h fi - JSON_LIBS="$LIBS" + + +# Check whether --with-libjson-static was given. +if test "${with_libjson_static+set}" = set; then : + withval=$with_libjson_static; + json_linking="static" + JSON_LIBS="$withval $LIBS" + +else + + json_linking="dynamic" + JSON_LIBS="-l${json_libname} $LIBS" + + +fi + fi LIBS="$save_LIBS" @@ -22932,70 +23303,126 @@ -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlib installation" >&5 -$as_echo_n "checking for zlib installation... " >&6; } - # Check whether --with-zlib was given. if test "${with_zlib+set}" = set; then : withval=$with_zlib; -if test "$withval"; then - ZLIB_HOME="$withval" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: using $ZLIB_HOME" >&5 -$as_echo "using $ZLIB_HOME" >&6; } + if test "$withval" != "no" -a "$withval" != "yes"; then + ZLIB_HOME=$withval + CPPFLAGS="${CPPFLAGS} -I$withval/include" + LDFLAGS="${LDFLAGS} -L$withval/lib" + fi + fi -else -ZLIB_HOME=/usr/local -if test ! -f "$ZLIB_HOME/include/zlib.h" -then - ZLIB_HOME=/usr -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZLIB_HOME" >&5 -$as_echo "$ZLIB_HOME" >&6; } +FOUND_ZLIB=0 +if test "x$ZLIB_HOME" = "x"; then +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ZLIB" >&5 +$as_echo_n "checking for ZLIB... " >&6; } + +if test -n "$ZLIB_CFLAGS"; then + pkg_cv_ZLIB_CFLAGS="$ZLIB_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_CFLAGS=`$PKG_CONFIG --cflags "zlib" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$ZLIB_LIBS"; then + pkg_cv_ZLIB_LIBS="$ZLIB_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"zlib\""; } >&5 + ($PKG_CONFIG --exists --print-errors "zlib") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_ZLIB_LIBS=`$PKG_CONFIG --libs "zlib" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried fi -CLAMDSCAN_LIBS="$FRESHCLAM_LIBS" -# Check whether --enable-zlib-vcheck was given. -if test "${enable_zlib_vcheck+set}" = set; then : - enableval=$enable_zlib_vcheck; zlib_check=$enableval +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes else - zlib_check="yes" + _pkg_short_errors_supported=no fi + if test $_pkg_short_errors_supported = yes; then + ZLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "zlib" 2>&1` + else + ZLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "zlib" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$ZLIB_PKG_ERRORS" >&5 - -if test ! -f "$ZLIB_HOME/include/zlib.h" -then - as_fn_error $? "Please install zlib and zlib-devel packages" "$LINENO" 5 + : +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + : else + ZLIB_CFLAGS=$pkg_cv_ZLIB_CFLAGS + ZLIB_LIBS=$pkg_cv_ZLIB_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } - vuln=`grep "ZLIB_VERSION \"1.2.0\"" $ZLIB_HOME/include/zlib.h` - if test -z "$vuln"; then - vuln=`grep "ZLIB_VERSION \"1.2.1\"" $ZLIB_HOME/include/zlib.h` - fi + FOUND_ZLIB=1 + $as_echo "#define HAVE_LIBZ 1" >>confdefs.h - if test -n "$vuln"; then - if test "$zlib_check" = "yes"; then - as_fn_error $? "The installed zlib version may contain a security bug. Please upgrade to 1.2.2 or later: http://www.zlib.net. You can omit this check with --disable-zlib-vcheck but DO NOT REPORT any stability issues then!" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** This ClamAV installation may be linked against" >&5 -$as_echo "$as_me: WARNING: ****** This ClamAV installation may be linked against" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** a broken zlib version. Please DO NOT report any" >&5 -$as_echo "$as_me: WARNING: ****** a broken zlib version. Please DO NOT report any" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** stability problems to the ClamAV developers!" >&5 -$as_echo "$as_me: WARNING: ****** stability problems to the ClamAV developers!" >&2;} - fi - fi + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF - save_LIBS="$LIBS" - if test "$ZLIB_HOME" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$ZLIB_HOME/include" - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -L$ZLIB_HOME/lib" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 +fi + +done + + +fi +fi + +if test "$FOUND_ZLIB" = "0"; then + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + + FOUND_ZLIB=1 + save_LIBS="$LIBS" + if test "x${ZLIB_HOME}" != "x"; then + save_CPPFLAGS="$CPPFLAGS -I$ZLIB_HOME/include" + save_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$ZLIB_HOME/include" + LDFLAGS="$LDFLAGS -L$ZLIB_HOME/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 @@ -23032,12 +23459,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : - LIBCLAMAV_LIBS="$LIBCLAMAV_LIBS -L$ZLIB_HOME/lib -lz"; FRESHCLAM_LIBS="$FRESHCLAM_LIBS -L$ZLIB_HOME/lib -lz" + ZLIB_CFLAGS="-I${ZLIB_HOME}/include"; ZLIB_LIBS="-L${ZLIB_HOME}/lib -lz" else as_fn_error $? "Please install zlib and zlib-devel packages" "$LINENO" 5 fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 $as_echo_n "checking for gzopen in -lz... " >&6; } if ${ac_cv_lib_z_gzopen+:} false; then : $as_echo_n "(cached) " >&6 @@ -23084,9 +23511,10 @@ as_fn_error $? "Your zlib is missing gzopen()" "$LINENO" 5 fi - LDFLAGS="$save_LDFLAGS" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inflateEnd in -lz" >&5 $as_echo_n "checking for inflateEnd in -lz... " >&6; } if ${ac_cv_lib_z_inflateEnd+:} false; then : $as_echo_n "(cached) " >&6 @@ -23123,12 +23551,12 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_inflateEnd" >&5 $as_echo "$ac_cv_lib_z_inflateEnd" >&6; } if test "x$ac_cv_lib_z_inflateEnd" = xyes; then : - LIBCLAMAV_LIBS="$LIBCLAMAV_LIBS -lz";FRESHCLAM_LIBS="$FRESHCLAM_LIBS -lz" + ZLIB_LIBS="-lz" else as_fn_error $? "Please install zlib and zlib-devel packages" "$LINENO" 5 fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzopen in -lz" >&5 $as_echo_n "checking for gzopen in -lz... " >&6; } if ${ac_cv_lib_z_gzopen+:} false; then : $as_echo_n "(cached) " >&6 @@ -23175,8 +23603,17 @@ as_fn_error $? "Your zlib is missing gzopen()" "$LINENO" 5 fi - fi - LIBS="$save_LIBS" + fi + LIBS="$save_LIBS" + +fi + +done + +fi + +if test "$FOUND_ZLIB" = "0"; then + as_fn_error $? "Please install zlib and zlib-devel packages" "$LINENO" 5 fi @@ -24625,161 +25062,885 @@ -# Check whether --with-iconv was given. -if test "${with_iconv+set}" = set; then : - withval=$with_iconv; - case "$withval" in - yes|no) wiconv="$withval";; - *) as_fn_error $? "--with-iconv does not take an argument" "$LINENO" 5;; - esac -else - wiconv=auto +# iconv.m4 serial 21 + + + + + + + + + + +if test "x$with_iconv" != "xno"; then + + + + + + + + + use_additional=yes + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + +# Check whether --with-libiconv-prefix was given. +if test "${with_libiconv_prefix+set}" = set; then : + withval=$with_libiconv_prefix; + if test "X$withval" = "Xno"; then + use_additional=no + else + additional_compat_libdir= + if test "X$withval" = "X"; then + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + + eval additional_includedir=\"$includedir\" + eval additional_libdir=\"$libdir\" + + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + else + additional_includedir="$withval/include" + additional_libdir="$withval/$acl_libdirstem" + if test "X$acl_libdirstem" != "Xlib"; then + additional_compat_libdir="-L$withval/lib" + fi + fi + fi + fi -if test "X$wiconv" != "Xno"; then - save_LDFLAGS="$LDFLAGS" - LDFLAGS="-L/usr/local/lib -liconv" - ICONV_HOME="" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv_open in -liconv" >&5 -$as_echo_n "checking for libiconv_open in -liconv... " >&6; } -if ${ac_cv_lib_iconv_libiconv_open+:} false; then : + LIBICONV= + LTLIBICONV= + INCICONV= + LIBICONV_PREFIX= + rpathdirs= + ltrpathdirs= + names_already_handled= + names_next_round='iconv ' + while test -n "$names_next_round"; do + names_this_round="$names_next_round" + names_next_round= + for name in $names_this_round; do + already_handled= + for n in $names_already_handled; do + if test "$n" = "$name"; then + already_handled=yes + break + fi + done + if test -z "$already_handled"; then + names_already_handled="$names_already_handled $name" + uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'` + eval value=\"\$HAVE_LIB$uppername\" + if test -n "$value"; then + if test "$value" = yes; then + eval value=\"\$LIB$uppername\" + test -z "$value" || LIBICONV="${LIBICONV}${LIBICONV:+ }$value" + eval value=\"\$LTLIB$uppername\" + test -z "$value" || LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$value" + else + : + fi + else + found_dir= + found_la= + found_so= + found_a= + eval libname=\"$acl_libname_spec\" # typically: libname=lib$name + if test -n "$acl_shlibext"; then + shrext=".$acl_shlibext" # typically: shrext=.so + else + shrext= + fi + if test $use_additional = yes; then + dir="$additional_libdir" + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + fi + if test "X$found_dir" = "X"; then + compat_libdir= + if test "X$acl_libdirstem" != "Xlib"; then + compat_libdir=-L'${exec_prefix}'/lib + fi + for x in $LDFLAGS $LTLIBICONV $compat_libdir $additional_compat_libdir; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + case "$x" in + -L*) + dir=`echo "X$x" | sed -e 's/^X-L//'` + if test -n "$acl_shlibext"; then + if test -f "$dir/$libname$shrext"; then + found_dir="$dir" + found_so="$dir/$libname$shrext" + else + if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then + ver=`(cd "$dir" && \ + for f in "$libname$shrext".*; do echo "$f"; done \ + | sed -e "s,^$libname$shrext\\\\.,," \ + | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \ + | sed 1q ) 2>/dev/null` + if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then + found_dir="$dir" + found_so="$dir/$libname$shrext.$ver" + fi + else + eval library_names=\"$acl_library_names_spec\" + for f in $library_names; do + if test -f "$dir/$f"; then + found_dir="$dir" + found_so="$dir/$f" + break + fi + done + fi + fi + fi + if test "X$found_dir" = "X"; then + if test -f "$dir/$libname.$acl_libext"; then + found_dir="$dir" + found_a="$dir/$libname.$acl_libext" + fi + fi + if test "X$found_dir" != "X"; then + if test -f "$dir/$libname.la"; then + found_la="$dir/$libname.la" + fi + fi + ;; + esac + if test "X$found_dir" != "X"; then + break + fi + done + fi + if test "X$found_dir" != "X"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$found_dir -l$name" + if test "X$found_so" != "X"; then + if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $found_dir" + fi + if test "$acl_hardcode_direct" = yes; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $found_dir" + fi + else + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$found_dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir" + fi + if test "$acl_hardcode_minus_L" != no; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_so" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + fi + fi + fi + fi + else + if test "X$found_a" != "X"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }$found_a" + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$found_dir -l$name" + fi + fi + additional_includedir= + case "$found_dir" in + */$acl_libdirstem | */$acl_libdirstem/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'` + LIBICONV_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + */lib | */lib/) + basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/lib/"'*$,,'` + LIBICONV_PREFIX="$basedir" + additional_includedir="$basedir/include" + ;; + esac + if test "X$additional_includedir" != "X"; then + if test "X$additional_includedir" != "X/usr/include"; then + haveit= + if test "X$additional_includedir" = "X/usr/local/include"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + for x in $CPPFLAGS $INCICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-I$additional_includedir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_includedir"; then + INCICONV="${INCICONV}${INCICONV:+ }-I$additional_includedir" + fi + fi + fi + fi + fi + if test -n "$found_la"; then + save_libdir="$libdir" + case "$found_la" in + */* | *\\*) . "$found_la" ;; + *) . "./$found_la" ;; + esac + libdir="$save_libdir" + for dep in $dependency_libs; do + case "$dep" in + -L*) + additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'` + if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then + haveit= + if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then + if test -n "$GCC"; then + case $host_os in + linux* | gnu* | k*bsd*-gnu) haveit=yes;; + esac + fi + fi + if test -z "$haveit"; then + haveit= + for x in $LDFLAGS $LIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LIBICONV="${LIBICONV}${LIBICONV:+ }-L$additional_libdir" + fi + fi + haveit= + for x in $LDFLAGS $LTLIBICONV; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X-L$additional_libdir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + if test -d "$additional_libdir"; then + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-L$additional_libdir" + fi + fi + fi + fi + ;; + -R*) + dir=`echo "X$dep" | sed -e 's/^X-R//'` + if test "$enable_rpath" != no; then + haveit= + for x in $rpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + rpathdirs="$rpathdirs $dir" + fi + haveit= + for x in $ltrpathdirs; do + if test "X$x" = "X$dir"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + ltrpathdirs="$ltrpathdirs $dir" + fi + fi + ;; + -l*) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'` + ;; + *.la) + names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'` + ;; + *) + LIBICONV="${LIBICONV}${LIBICONV:+ }$dep" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }$dep" + ;; + esac + done + fi + else + LIBICONV="${LIBICONV}${LIBICONV:+ }-l$name" + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-l$name" + fi + fi + fi + done + done + if test "X$rpathdirs" != "X"; then + if test -n "$acl_hardcode_libdir_separator"; then + alldirs= + for found_dir in $rpathdirs; do + alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir" + done + acl_save_libdir="$libdir" + libdir="$alldirs" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + else + for found_dir in $rpathdirs; do + acl_save_libdir="$libdir" + libdir="$found_dir" + eval flag=\"$acl_hardcode_libdir_flag_spec\" + libdir="$acl_save_libdir" + LIBICONV="${LIBICONV}${LIBICONV:+ }$flag" + done + fi + fi + if test "X$ltrpathdirs" != "X"; then + for found_dir in $ltrpathdirs; do + LTLIBICONV="${LTLIBICONV}${LTLIBICONV:+ }-R$found_dir" + done + fi + + + + + + + + am_save_CPPFLAGS="$CPPFLAGS" + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 +$as_echo_n "checking for iconv... " >&6; } +if ${am_cv_func_iconv+:} false; then : $as_echo_n "(cached) " >&6 else - ac_check_lib_save_LIBS=$LIBS -LIBS="-liconv $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + + am_cv_func_iconv="no, consider installing GNU libiconv" + am_cv_lib_iconv=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char libiconv_open (); +#include +#include + int main () { -return libiconv_open (); +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_iconv_libiconv_open=yes -else - ac_cv_lib_iconv_libiconv_open=no + am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv_open" >&5 -$as_echo "$ac_cv_lib_iconv_libiconv_open" >&6; } -if test "x$ac_cv_lib_iconv_libiconv_open" = xyes; then : - ICONV_HOME="/usr/local" -else - - LDFLAGS="-L/usr/lib -liconv" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv_open in -liconv" >&5 -$as_echo_n "checking for libiconv_open in -liconv... " >&6; } -if ${ac_cv_lib_iconv_libiconv_open+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-liconv $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "$am_cv_func_iconv" != yes; then + am_save_LIBS="$LIBS" + LIBS="$LIBS $LIBICONV" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char libiconv_open (); +#include +#include + int main () { -return libiconv_open (); +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_iconv_libiconv_open=yes -else - ac_cv_lib_iconv_libiconv_open=no + am_cv_lib_iconv=yes + am_cv_func_iconv=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS + LIBS="$am_save_LIBS" + fi + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv_open" >&5 -$as_echo "$ac_cv_lib_iconv_libiconv_open" >&6; } -if test "x$ac_cv_lib_iconv_libiconv_open" = xyes; then : - ICONV_HOME="/usr" +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv" >&5 +$as_echo "$am_cv_func_iconv" >&6; } + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working iconv" >&5 +$as_echo_n "checking for working iconv... " >&6; } +if ${am_cv_func_iconv_works+:} false; then : + $as_echo_n "(cached) " >&6 else - LDFLAGS="$save_LDFLAGS" + + am_save_LIBS="$LIBS" + if test $am_cv_lib_iconv = yes; then + LIBS="$LIBS $LIBICONV" + fi + am_cv_func_iconv_works=no + for ac_iconv_const in '' 'const'; do + if test "$cross_compiling" = yes; then : + case "$host_os" in + aix* | hpux*) am_cv_func_iconv_works="guessing no" ;; + *) am_cv_func_iconv_works="guessing yes" ;; + esac +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include + +#ifndef ICONV_CONST +# define ICONV_CONST $ac_iconv_const +#endif + +int +main () +{ +int result = 0; + /* Test against AIX 5.1 bug: Failures are not distinguishable from successful + returns. */ + { + iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8"); + if (cd_utf8_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */ + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_utf8_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 1; + iconv_close (cd_utf8_to_88591); + } + } + /* Test against Solaris 10 bug: Failures are not distinguishable from + successful returns. */ + { + iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646"); + if (cd_ascii_to_88591 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\263"; + char buf[10]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_ascii_to_88591, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res == 0) + result |= 2; + iconv_close (cd_ascii_to_88591); + } + } + /* Test against AIX 6.1..7.1 bug: Buffer overrun. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304"; + static char buf[2] = { (char)0xDE, (char)0xAD }; + ICONV_CONST char *inptr = input; + size_t inbytesleft = 1; + char *outptr = buf; + size_t outbytesleft = 1; + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD) + result |= 4; + iconv_close (cd_88591_to_utf8); + } + } +#if 0 /* This bug could be worked around by the caller. */ + /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */ + { + iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591"); + if (cd_88591_to_utf8 != (iconv_t)(-1)) + { + static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337"; + char buf[50]; + ICONV_CONST char *inptr = input; + size_t inbytesleft = strlen (input); + char *outptr = buf; + size_t outbytesleft = sizeof (buf); + size_t res = iconv (cd_88591_to_utf8, + &inptr, &inbytesleft, + &outptr, &outbytesleft); + if ((int)res > 0) + result |= 8; + iconv_close (cd_88591_to_utf8); + } + } +#endif + /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is + provided. */ + { + /* Try standardized names. */ + iconv_t cd1 = iconv_open ("UTF-8", "EUC-JP"); + /* Try IRIX, OSF/1 names. */ + iconv_t cd2 = iconv_open ("UTF-8", "eucJP"); + /* Try AIX names. */ + iconv_t cd3 = iconv_open ("UTF-8", "IBM-eucJP"); + /* Try HP-UX names. */ + iconv_t cd4 = iconv_open ("utf8", "eucJP"); + if (cd1 == (iconv_t)(-1) && cd2 == (iconv_t)(-1) + && cd3 == (iconv_t)(-1) && cd4 == (iconv_t)(-1)) + result |= 16; + if (cd1 != (iconv_t)(-1)) + iconv_close (cd1); + if (cd2 != (iconv_t)(-1)) + iconv_close (cd2); + if (cd3 != (iconv_t)(-1)) + iconv_close (cd3); + if (cd4 != (iconv_t)(-1)) + iconv_close (cd4); + } + return result; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + am_cv_func_iconv_works=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext fi + test "$am_cv_func_iconv_works" = no || break + done + LIBS="$am_save_LIBS" fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_func_iconv_works" >&5 +$as_echo "$am_cv_func_iconv_works" >&6; } + case "$am_cv_func_iconv_works" in + *no) am_func_iconv=no am_cv_lib_iconv=no ;; + *) am_func_iconv=yes ;; + esac + else + am_func_iconv=no am_cv_lib_iconv=no + fi + if test "$am_func_iconv" = yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 -$as_echo_n "checking for iconv... " >&6; } - save_LIBS="$LIBS" - save_CPPFLAGS="$CPPFLAGS" - LIBS="$LIBCLAMAV_LIBS" - if test "X$ICONV_HOME" != "X"; then - ICONV_LDFLAGS="$LDFLAGS" - ICONV_CPPFLAGS="-I$ICONV_HOME/include" - else - ICONV_LDFLAGS="" - ICONV_CPPFLAGS="" - fi - CPPFLAGS="$ICONV_CPPFLAGS $LIBCLAMAV_CPPFLAGS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext +$as_echo "#define HAVE_ICONV 1" >>confdefs.h + + fi + if test "$am_cv_lib_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 +$as_echo_n "checking how to link with libiconv... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 +$as_echo "$LIBICONV" >&6; } + else + CPPFLAGS="$am_save_CPPFLAGS" + LIBICONV= + LTLIBICONV= + fi + + + + if test "$am_cv_func_iconv" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 +$as_echo_n "checking for iconv declaration... " >&6; } + if ${am_cv_proto_iconv+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include +#include +#include +extern +#ifdef __cplusplus +"C" +#endif +#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) +size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); +#else +size_t iconv(); +#endif int main () { - char** xin,**xout; - unsigned long il,ol; - int rc; - iconv_t iconv_struct = iconv_open("UTF-16BE","UTF-8"); - rc = iconv(iconv_struct,xin,&il,xout,&ol); - iconv_close(iconv_struct); - ; return 0; } _ACEOF -if ac_fn_c_try_link "$LINENO"; then : +if ac_fn_c_try_compile "$LINENO"; then : + am_cv_proto_iconv_arg1="" +else + am_cv_proto_iconv_arg1="const" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);" +fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + am_cv_proto_iconv=`echo "$am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: result: + $am_cv_proto_iconv" >&5 +$as_echo " + $am_cv_proto_iconv" >&6; } + else + am_cv_proto_iconv_arg1="" + fi -$as_echo "#define HAVE_ICONV 1" >>confdefs.h +cat >>confdefs.h <<_ACEOF +#define ICONV_CONST $am_cv_proto_iconv_arg1 +_ACEOF + for ac_header in iconv.h +do : + ac_fn_c_check_header_compile "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "#include +" +if test "x$ac_cv_header_iconv_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ICONV_H 1 +_ACEOF + +fi -else +done - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } + if test "x$am_cv_func_iconv" = "xyes"; then + for ac_header in localcharset.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "localcharset.h" "ac_cv_header_localcharset_h" "$ac_includes_default" +if test "x$ac_cv_header_localcharset_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALCHARSET_H 1 +_ACEOF + +fi + +done + + am_save_LIBS="$LIBS" + LIBS="${LIBS} ${LIBICONV}" + for ac_func in locale_charset +do : + ac_fn_c_check_func "$LINENO" "locale_charset" "ac_cv_func_locale_charset" +if test "x$ac_cv_func_locale_charset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LOCALE_CHARSET 1 +_ACEOF + +fi +done + LIBS="${am_save_LIBS}" + if test "x$ac_cv_func_locale_charset" != "xyes"; then + # If locale_charset() is not in libiconv, we have to find libcharset. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for locale_charset in -lcharset" >&5 +$as_echo_n "checking for locale_charset in -lcharset... " >&6; } +if ${ac_cv_lib_charset_locale_charset+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcharset $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char locale_charset (); +int +main () +{ +return locale_charset (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_charset_locale_charset=yes +else + ac_cv_lib_charset_locale_charset=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LIBS="$save_LIBS" - LDFLAGS="$save_LDFLAGS" - CPPFLAGS="$save_CPPFLAGS" +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_charset_locale_charset" >&5 +$as_echo "$ac_cv_lib_charset_locale_charset" >&6; } +if test "x$ac_cv_lib_charset_locale_charset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCHARSET 1 +_ACEOF + + LIBS="-lcharset $LIBS" + +fi + + fi + fi fi have_pthreads=no @@ -25469,87 +26630,6 @@ fi - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for readdir_r" >&5 -$as_echo_n "checking for readdir_r... " >&6; } -if test -z "$ac_cv_readdir_args"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include - -int -main () -{ - - struct dirent dir, *dirp; - DIR *mydir; - dirp = readdir_r(mydir, &dir); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_readdir_args=2 -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -if test -z "$ac_cv_readdir_args"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -#include -#include - -int -main () -{ - - struct dirent dir, *dirp; - DIR *mydir; - int rc; - rc = readdir_r(mydir, &dir, &dirp); - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_readdir_args=3 -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi - -# Check whether --enable-readdir_r was given. -if test "${enable_readdir_r+set}" = set; then : - enableval=$enable_readdir_r; enable_readdir_r=$enableval -else - enable_readdir_r="no" -fi - - -if test "$enable_readdir_r" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: support disabled" >&5 -$as_echo "support disabled" >&6; } -elif test -z "$ac_cv_readdir_args"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -else - if test "$ac_cv_readdir_args" = 2; then - -$as_echo "#define HAVE_READDIR_R_2 1" >>confdefs.h - - elif test "$ac_cv_readdir_args" = 3; then - -$as_echo "#define HAVE_READDIR_R_3 1" >>confdefs.h - - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, and it takes $ac_cv_readdir_args arguments" >&5 -$as_echo "yes, and it takes $ac_cv_readdir_args arguments" >&6; } -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ctime_r" >&5 $as_echo_n "checking for ctime_r... " >&6; } if test "$ac_cv_func_ctime_r" = "yes"; then @@ -28505,37 +29585,6 @@ lfs_fts_msg="internal, libc's is not LFS compatible" fi - if test "$have_curl" = "yes"; then - ENABLE_CLAMSUBMIT_TRUE= - ENABLE_CLAMSUBMIT_FALSE='#' -else - ENABLE_CLAMSUBMIT_TRUE='#' - ENABLE_CLAMSUBMIT_FALSE= -fi - - -# Check whether --enable-libfreshclam was given. -if test "${enable_libfreshclam+set}" = set; then : - enableval=$enable_libfreshclam; enable_libfreshclam=$enableval -else - enable_libfreshclam="no" -fi - - -if test "$enable_libfreshclam" = "yes"; then - -$as_echo "#define ENABLE_LIBFRESHCLAM 1" >>confdefs.h - -fi - if test "$enable_libfreshclam" = "yes"; then - ENABLE_LIBFRESHCLAM_TRUE= - ENABLE_LIBFRESHCLAM_FALSE='#' -else - ENABLE_LIBFRESHCLAM_TRUE='#' - ENABLE_LIBFRESHCLAM_FALSE= -fi - - # PRELUDE # Check whether --enable-prelude was given. if test "${enable_prelude+set}" = set; then : @@ -28844,6 +29893,57 @@ esac +# Check whether --enable-clamonacc was given. +if test "${enable_clamonacc+set}" = set; then : + enableval=$enable_clamonacc; enable_clamonacc=$enableval +else + enable_clamonacc="auto" +fi + + +if test "$enable_libclamav_only" != yes; then + +if test "$enable_clamonacc" != "no"; then + + + case "${host_os}" in + linux*) + if test x$enable_clamonacc != xno; then + BUILD_CLAMONACC_TRUE= + BUILD_CLAMONACC_FALSE='#' +else + BUILD_CLAMONACC_TRUE='#' + BUILD_CLAMONACC_FALSE= +fi + + ;; + *) + if test "$enable_clamonacc" == "yes"; then + as_fn_error $? "Clamonacc was explicitly requested, but the platform ($host_os) you are trying to build on is not currently supported for this tool." "$LINENO" 5 + fi + if test x$enable_clamonacc == xno; then + BUILD_CLAMONACC_TRUE= + BUILD_CLAMONACC_FALSE='#' +else + BUILD_CLAMONACC_TRUE='#' + BUILD_CLAMONACC_FALSE= +fi + + ;; + esac +else + if test x$enable_clamonacc == xyes; then + BUILD_CLAMONACC_TRUE= + BUILD_CLAMONACC_FALSE='#' +else + BUILD_CLAMONACC_TRUE='#' + BUILD_CLAMONACC_FALSE= +fi + +fi +fi + + have_curl="no" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcurl installation" >&5 @@ -28883,26 +29983,129 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBCURL_HOME" >&5 $as_echo "$LIBCURL_HOME" >&6; } if test -f "$LIBCURL_HOME/bin/curl-config"; then - CURL_LDFLAGS=$($LIBCURL_HOME/bin/curl-config --libs) + CURL_LDFLAGS="$LDFLAGS" + CURL_LIBS=$($LIBCURL_HOME/bin/curl-config --libs) CURL_CPPFLAGS=$($LIBCURL_HOME/bin/curl-config --cflags) else if test "$LIBCURL_HOME" != "/usr"; then - CURL_LDFLAGS="-L$LIBCURL_HOME/lib -lcurl" + CURL_LDFLAGS="-L$LIBCURL_HOME/lib" CURL_CPPFLAGS="-I$LIBCURL_HOME/include" else - CURL_LDFLAGS="-lcurl" + CURL_LDFLAGS="$LDFLAGS" CURL_CPPFLAGS="" fi + CURL_LIBS="-lcurl" fi save_LDFLAGS="$LDFLAGS" - LDFLAGS="$CURL_LDFLAGS" + LDFLAGS="$CURL_LDFLAGS $CURL_LIBS $SSL_LDFLAGS $SSL_LIBS" + + for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + curl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[1]+256*A[2]+A[3]; print X;}'" + # Extract the first word of "curl-config", so it can be a program name with args. +set dummy curl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_curl_config+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $curl_config in + [\\/]* | ?:[\\/]*) + ac_cv_path_curl_config="$curl_config" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in "$LIBCURL_HOME/bin" +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_curl_config="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_curl_config" && ac_cv_path_curl_config=""notfound"" + ;; +esac +fi +curl_config=$ac_cv_path_curl_config +if test -n "$curl_config"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $curl_config" >&5 +$as_echo "$curl_config" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + awk_curl_version=`$curl_config --version | $AWK '{print $2}'` + curl_version=`echo $awk_curl_version | $curl_version_parse` + + if test -z "$BUILD_CLAMONACC_TRUE"; then : + if test $curl_version -ge 470272 ; then + $enable_clamonacc="yes" + else + as_fn_error $? "Your libcurl (e.g. libcurl-devel) is too old. Installing ClamAV with clamonacc requires libcurl 7.45 or higher. For a quick fix, run ./configure again with --disable-clamonacc if you do not wish to use on-access scanning features. For more information on ClamAV's on-access scanner, please read our documentation: https://www.clamav.net/documents/on-access-scanning#on-access-scanning" "$LINENO" 5 + fi + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init in -lcurl" >&5 $as_echo_n "checking for curl_easy_init in -lcurl... " >&6; } if ${ac_cv_lib_curl_curl_easy_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS -LIBS="-lcurl $CURL_LDFLAGS $LIBS" +LIBS="-lcurl $CURL_LIBS + $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -28933,16 +30136,24 @@ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init" >&5 $as_echo "$ac_cv_lib_curl_curl_easy_init" >&6; } if test "x$ac_cv_lib_curl_curl_easy_init" = xyes; then : - curl_msg="";have_curl="yes";CLAMSUBMIT_LIBS="$CLAMSUBMIT_LIBS $CURL_LDFLAGS";CLAMSUBMIT_CFLAGS="$CLAMSUBMIT_CFLAGS $CURL_CPPFLAGS" + + curl_msg=""; + have_curl="yes"; + CLAMSUBMIT_LIBS="$CLAMSUBMIT_LIBS $CURL_LDFLAGS $CURL_LIBS"; + CLAMSUBMIT_CFLAGS="$CLAMSUBMIT_CFLAGS $CURL_CPPFLAGS"; + FRESHCLAM_LIBS="$FRESHCLAM_LIBS $CURL_LDFLAGS $CURL_LIBS"; + FRESHCLAM_CPPFLAGS="$FRESHCLAM_CPPFLAGS $CURL_CPPFLAGS" + else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Your libcurl is misconfigured. Please use the web interface for submitting FPs/FNs." >&5 -$as_echo "$as_me: WARNING: Your libcurl is misconfigured. Please use the web interface for submitting FPs/FNs." >&2;} + + as_fn_error $? "Your libcurl is misconfigured. libcurl (e.g. libcurl-devel) is required in order to build freshclam and clamsubmit." "$LINENO" 5 + fi + LDFLAGS="$save_LDFLAGS" else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libcurl not found or not requested by ./configure. Please use the web interface for submitting FPs/FNs." >&5 -$as_echo "$as_me: WARNING: libcurl not found or not requested by ./configure. Please use the web interface for submitting FPs/FNs." >&2;} + as_fn_error $? "libcurl not found. libcurl (e.g. libcurl-devel) is required in order to build freshclam and clamsubmit." "$LINENO" 5 fi @@ -28986,6 +30197,10 @@ + + + + # Check whether --enable-strni was given. if test "${enable_strni+set}" = set; then : enableval=$enable_strni; enable_strni=$enableval @@ -29210,8 +30425,439 @@ mspack_msg="External, $LIBMSPACK_CFLAGS $LIBMSPACK_LIBS" fi -ac_config_files="$ac_config_files clamscan/Makefile database/Makefile docs/Makefile clamd/Makefile clamd/clamav-daemon.service clamd/clamav-daemon.socket clamdscan/Makefile clamsubmit/Makefile clamav-milter/Makefile freshclam/clamav-freshclam.service freshclam/Makefile sigtool/Makefile clamconf/Makefile etc/Makefile test/Makefile unit_tests/Makefile fuzz/Makefile clamdtop/Makefile clambc/Makefile libfreshclam/Makefile Makefile clamav-config libclamav.pc platform.h docs/man/clamav-milter.8 docs/man/clamav-milter.conf.5 docs/man/clambc.1 docs/man/clamconf.1 docs/man/clamd.8 docs/man/clamd.conf.5 docs/man/clamdscan.1 docs/man/clamscan.1 docs/man/freshclam.1 docs/man/freshclam.conf.5 docs/man/sigtool.1 docs/man/clamdtop.1 docs/man/clamsubmit.1 clamav-types.h" +ac_ext=m +ac_cpp='$OBJCPP $CPPFLAGS' +ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$OBJC -o conftest$ac_exeext $OBJCFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_objc_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in gcc objcc objc cc CC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJC"; then + ac_cv_prog_OBJC="$OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJC=$ac_cv_prog_OBJC +if test -n "$OBJC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJC" >&5 +$as_echo "$OBJC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$OBJC" && break + done +fi +if test -z "$OBJC"; then + ac_ct_OBJC=$OBJC + for ac_prog in gcc objcc objc cc CC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJC"; then + ac_cv_prog_ac_ct_OBJC="$ac_ct_OBJC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJC=$ac_cv_prog_ac_ct_OBJC +if test -n "$ac_ct_OBJC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJC" >&5 +$as_echo "$ac_ct_OBJC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_OBJC" && break +done + + if test "x$ac_ct_OBJC" = x; then + OBJC="gcc" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJC=$ac_ct_OBJC + fi +fi + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for Objective C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Objective C compiler" >&5 +$as_echo_n "checking whether we are using the GNU Objective C compiler... " >&6; } +if ${ac_cv_objc_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_objc_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objc_compiler_gnu" >&5 +$as_echo "$ac_cv_objc_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GOBJC=yes +else + GOBJC= +fi +ac_test_OBJCFLAGS=${OBJCFLAGS+set} +ac_save_OBJCFLAGS=$OBJCFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $OBJC accepts -g" >&5 +$as_echo_n "checking whether $OBJC accepts -g... " >&6; } +if ${ac_cv_prog_objc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_objc_werror_flag=$ac_objc_werror_flag + ac_objc_werror_flag=yes + ac_cv_prog_objc_g=no + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_cv_prog_objc_g=yes +else + OBJCFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + +else + ac_objc_werror_flag=$ac_save_objc_werror_flag + OBJCFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_objc_try_compile "$LINENO"; then : + ac_cv_prog_objc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_objc_werror_flag=$ac_save_objc_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_objc_g" >&5 +$as_echo "$ac_cv_prog_objc_g" >&6; } +if test "$ac_test_OBJCFLAGS" = set; then + OBJCFLAGS=$ac_save_OBJCFLAGS +elif test $ac_cv_prog_objc_g = yes; then + if test "$GOBJC" = yes; then + OBJCFLAGS="-g -O2" + else + OBJCFLAGS="-g" + fi +else + if test "$GOBJC" = yes; then + OBJCFLAGS="-O2" + else + OBJCFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$OBJC" am_compiler_list='gcc3 gcc' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_OBJC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_OBJC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_OBJC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_OBJC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_OBJC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_OBJC_dependencies_compiler_type" >&6; } +OBJCDEPMODE=depmode=$am_cv_OBJC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_OBJC_dependencies_compiler_type" = gcc3; then + am__fastdepOBJC_TRUE= + am__fastdepOBJC_FALSE='#' +else + am__fastdepOBJC_TRUE='#' + am__fastdepOBJC_FALSE= +fi + + + +build_linux=no +build_windows=no +build_mac=no + + + +case "${host_os}" in + cygwin*|mingw*) + build_windows=yes + ;; + darwin*) + build_mac=yes + ;; + *) + build_linux=yes + ;; +esac + + if test "$build_linux" = "yes"; then + LINUX_TRUE= + LINUX_FALSE='#' +else + LINUX_TRUE='#' + LINUX_FALSE= +fi + + if test "$build_windows" = "yes"; then + WINDOWS_TRUE= + WINDOWS_FALSE='#' +else + WINDOWS_TRUE='#' + WINDOWS_FALSE= +fi + + if test "$build_mac" = "yes"; then + MACOS_TRUE= + MACOS_FALSE='#' +else + MACOS_TRUE='#' + MACOS_FALSE= +fi + + + +ac_config_files="$ac_config_files Makefile clamav-config libclamav.pc platform.h clamav-types.h clamav-version.h" + +if test "x$enable_libclamav_only" != "xyes"; then + ac_config_files="$ac_config_files clamscan/Makefile database/Makefile docs/Makefile clamd/Makefile clamd/clamav-daemon.service clamd/clamav-daemon.socket clamdscan/Makefile clamsubmit/Makefile clamav-milter/Makefile freshclam/clamav-freshclam.service freshclam/Makefile sigtool/Makefile clamconf/Makefile etc/Makefile test/Makefile unit_tests/Makefile fuzz/Makefile clamdtop/Makefile clambc/Makefile libfreshclam/Makefile docs/man/clamav-milter.8 docs/man/clamav-milter.conf.5 docs/man/clambc.1 docs/man/clamconf.1 docs/man/clamd.8 docs/man/clamd.conf.5 docs/man/clamdscan.1 docs/man/clamscan.1 docs/man/freshclam.1 docs/man/freshclam.conf.5 docs/man/sigtool.1 docs/man/clamdtop.1 docs/man/clamsubmit.1" + +fi + +if test -z "$BUILD_CLAMONACC_TRUE"; then : + ac_config_files="$ac_config_files clamonacc/Makefile" + +fi # Define variables needed to generate clamav-types.h. # Define a warning for the user, so they don't edit clamav-types.h @@ -29516,6 +31162,14 @@ ltdl_LTLIBOBJS=$_ltdl_ltlibobjs +if test -z "${BUILD_LIBCLAMAV_ONLY_TRUE}" && test -z "${BUILD_LIBCLAMAV_ONLY_FALSE}"; then + as_fn_error $? "conditional \"BUILD_LIBCLAMAV_ONLY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -29581,12 +31235,32 @@ as_fn_error $? "conditional \"SYSTEM_LFS_FTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_CLAMSUBMIT_TRUE}" && test -z "${ENABLE_CLAMSUBMIT_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_CLAMSUBMIT\" was never defined. +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_LIBFRESHCLAM_TRUE}" && test -z "${ENABLE_LIBFRESHCLAM_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_LIBFRESHCLAM\" was never defined. +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepOBJC_TRUE}" && test -z "${am__fastdepOBJC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepOBJC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then + as_fn_error $? "conditional \"LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then + as_fn_error $? "conditional \"WINDOWS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${MACOS_TRUE}" && test -z "${MACOS_FALSE}"; then + as_fn_error $? "conditional \"MACOS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi @@ -29986,7 +31660,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ClamAV $as_me 0.101.4, which was +This file was extended by ClamAV $as_me 0.102.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -30053,7 +31727,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ClamAV config.status 0.101.4 +ClamAV config.status 0.102.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -30568,6 +32242,12 @@ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "libltdl/Makefile") CONFIG_FILES="$CONFIG_FILES libltdl/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "clamav-config") CONFIG_FILES="$CONFIG_FILES clamav-config" ;; + "libclamav.pc") CONFIG_FILES="$CONFIG_FILES libclamav.pc" ;; + "platform.h") CONFIG_FILES="$CONFIG_FILES platform.h" ;; + "clamav-types.h") CONFIG_FILES="$CONFIG_FILES clamav-types.h" ;; + "clamav-version.h") CONFIG_FILES="$CONFIG_FILES clamav-version.h" ;; "clamscan/Makefile") CONFIG_FILES="$CONFIG_FILES clamscan/Makefile" ;; "database/Makefile") CONFIG_FILES="$CONFIG_FILES database/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; @@ -30588,10 +32268,6 @@ "clamdtop/Makefile") CONFIG_FILES="$CONFIG_FILES clamdtop/Makefile" ;; "clambc/Makefile") CONFIG_FILES="$CONFIG_FILES clambc/Makefile" ;; "libfreshclam/Makefile") CONFIG_FILES="$CONFIG_FILES libfreshclam/Makefile" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "clamav-config") CONFIG_FILES="$CONFIG_FILES clamav-config" ;; - "libclamav.pc") CONFIG_FILES="$CONFIG_FILES libclamav.pc" ;; - "platform.h") CONFIG_FILES="$CONFIG_FILES platform.h" ;; "docs/man/clamav-milter.8") CONFIG_FILES="$CONFIG_FILES docs/man/clamav-milter.8" ;; "docs/man/clamav-milter.conf.5") CONFIG_FILES="$CONFIG_FILES docs/man/clamav-milter.conf.5" ;; "docs/man/clambc.1") CONFIG_FILES="$CONFIG_FILES docs/man/clambc.1" ;; @@ -30605,7 +32281,7 @@ "docs/man/sigtool.1") CONFIG_FILES="$CONFIG_FILES docs/man/sigtool.1" ;; "docs/man/clamdtop.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamdtop.1" ;; "docs/man/clamsubmit.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamsubmit.1" ;; - "clamav-types.h") CONFIG_FILES="$CONFIG_FILES clamav-types.h" ;; + "clamonacc/Makefile") CONFIG_FILES="$CONFIG_FILES clamonacc/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -31309,7 +32985,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. @@ -32389,6 +34064,14 @@ ltdl_LTLIBOBJS=$_ltdl_ltlibobjs +if test -z "${BUILD_LIBCLAMAV_ONLY_TRUE}" && test -z "${BUILD_LIBCLAMAV_ONLY_FALSE}"; then + as_fn_error $? "conditional \"BUILD_LIBCLAMAV_ONLY\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -32454,12 +34137,32 @@ as_fn_error $? "conditional \"SYSTEM_LFS_FTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_CLAMSUBMIT_TRUE}" && test -z "${ENABLE_CLAMSUBMIT_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_CLAMSUBMIT\" was never defined. +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${BUILD_CLAMONACC_TRUE}" && test -z "${BUILD_CLAMONACC_FALSE}"; then + as_fn_error $? "conditional \"BUILD_CLAMONACC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepOBJC_TRUE}" && test -z "${am__fastdepOBJC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepOBJC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${LINUX_TRUE}" && test -z "${LINUX_FALSE}"; then + as_fn_error $? "conditional \"LINUX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then + as_fn_error $? "conditional \"WINDOWS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${ENABLE_LIBFRESHCLAM_TRUE}" && test -z "${ENABLE_LIBFRESHCLAM_FALSE}"; then - as_fn_error $? "conditional \"ENABLE_LIBFRESHCLAM\" was never defined. +if test -z "${MACOS_TRUE}" && test -z "${MACOS_FALSE}"; then + as_fn_error $? "conditional \"MACOS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__EXEEXT_TRUE}" && test -z "${am__EXEEXT_FALSE}"; then @@ -32875,7 +34578,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ClamAV $as_me 0.101.4, which was +This file was extended by ClamAV $as_me 0.102.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -32942,7 +34645,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ClamAV config.status 0.101.4 +ClamAV config.status 0.102.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -33458,6 +35161,12 @@ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "libltdl/Makefile") CONFIG_FILES="$CONFIG_FILES libltdl/Makefile" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "clamav-config") CONFIG_FILES="$CONFIG_FILES clamav-config" ;; + "libclamav.pc") CONFIG_FILES="$CONFIG_FILES libclamav.pc" ;; + "platform.h") CONFIG_FILES="$CONFIG_FILES platform.h" ;; + "clamav-types.h") CONFIG_FILES="$CONFIG_FILES clamav-types.h" ;; + "clamav-version.h") CONFIG_FILES="$CONFIG_FILES clamav-version.h" ;; "clamscan/Makefile") CONFIG_FILES="$CONFIG_FILES clamscan/Makefile" ;; "database/Makefile") CONFIG_FILES="$CONFIG_FILES database/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; @@ -33478,10 +35187,6 @@ "clamdtop/Makefile") CONFIG_FILES="$CONFIG_FILES clamdtop/Makefile" ;; "clambc/Makefile") CONFIG_FILES="$CONFIG_FILES clambc/Makefile" ;; "libfreshclam/Makefile") CONFIG_FILES="$CONFIG_FILES libfreshclam/Makefile" ;; - "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "clamav-config") CONFIG_FILES="$CONFIG_FILES clamav-config" ;; - "libclamav.pc") CONFIG_FILES="$CONFIG_FILES libclamav.pc" ;; - "platform.h") CONFIG_FILES="$CONFIG_FILES platform.h" ;; "docs/man/clamav-milter.8") CONFIG_FILES="$CONFIG_FILES docs/man/clamav-milter.8" ;; "docs/man/clamav-milter.conf.5") CONFIG_FILES="$CONFIG_FILES docs/man/clamav-milter.conf.5" ;; "docs/man/clambc.1") CONFIG_FILES="$CONFIG_FILES docs/man/clambc.1" ;; @@ -33495,7 +35200,7 @@ "docs/man/sigtool.1") CONFIG_FILES="$CONFIG_FILES docs/man/sigtool.1" ;; "docs/man/clamdtop.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamdtop.1" ;; "docs/man/clamsubmit.1") CONFIG_FILES="$CONFIG_FILES docs/man/clamsubmit.1" ;; - "clamav-types.h") CONFIG_FILES="$CONFIG_FILES clamav-types.h" ;; + "clamonacc/Makefile") CONFIG_FILES="$CONFIG_FILES clamonacc/Makefile" ;; "libclamav/Makefile") CONFIG_FILES="$CONFIG_FILES libclamav/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; @@ -34200,7 +35905,6 @@ cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. @@ -35167,65 +36871,111 @@ fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: Summary of optional tools" >&5 + + $as_echo_n " openssl : " + if test "xyes" = "xno"; then : + $as_echo "$LIBSSL_HOME (disabled)" +elif test "xyes" = "xyes"; then : + $as_echo "$LIBSSL_HOME" +elif test "xyes" = "x"; then : + $as_echo "$LIBSSL_HOME" +else + $as_echo "$LIBSSL_HOME (yes)" +fi + + + + $as_echo_n " libcurl : " + if test "xyes" = "xno"; then : + $as_echo "$LIBCURL_HOME (disabled)" +elif test "xyes" = "xyes"; then : + $as_echo "$LIBCURL_HOME" +elif test "xyes" = "x"; then : + $as_echo "$LIBCURL_HOME" +else + $as_echo "$LIBCURL_HOME (yes)" +fi + + +if test "x$enable_libclamav_only" != "xyes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Summary of optional tools" >&5 $as_echo "$as_me: Summary of optional tools" >&6;} + if test "X$HAVE_LIBNCURSES" = "Xyes" || test "X$HAVE_LIBPDCURSES" = "Xyes"; then + $as_echo_n " clamdtop : " - if test "x$enable_clamdtop" = "xno"; then : - $as_echo "$CURSES_LIBS (disabled)" -elif test "x$enable_clamdtop" = "xyes"; then : - $as_echo "$CURSES_LIBS" -elif test "x$enable_clamdtop" = "x"; then : - $as_echo "$CURSES_LIBS" + if test "xyes" = "xno"; then : + $as_echo "yes ($CURSES_LIBS) (disabled)" +elif test "xyes" = "xyes"; then : + $as_echo "yes ($CURSES_LIBS)" +elif test "xyes" = "x"; then : + $as_echo "yes ($CURSES_LIBS)" else - $as_echo "$CURSES_LIBS ($enable_clamdtop)" + $as_echo "yes ($CURSES_LIBS) (yes)" fi + else - $as_echo_n " milter : " - if test "x$have_milter" = "xno"; then : - $as_echo "yes (disabled)" -elif test "x$have_milter" = "xyes"; then : - $as_echo "yes" -elif test "x$have_milter" = "x"; then : - $as_echo "yes" + $as_echo_n " clamdtop : " + if test "xno" = "xno"; then : + $as_echo "no (missing ncurses / pdcurses) (disabled)" +elif test "xno" = "xyes"; then : + $as_echo "no (missing ncurses / pdcurses)" +elif test "xno" = "x"; then : + $as_echo "no (missing ncurses / pdcurses)" else - $as_echo "yes ($have_milter)" + $as_echo "no (missing ncurses / pdcurses) (no)" fi -if test "X$have_curl" = "Xyes" && test "X$have_json" = "Xyes"; then + fi + if test "X$have_milter" = "Xyes"; then - $as_echo_n " clamsubmit : " + + $as_echo_n " milter : " if test "xyes" = "xno"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME), libcurl-devel found at $LIBCURL_HOME) (disabled)" + $as_echo "yes ($CLAMAV_MILTER_LIBS) (disabled)" elif test "xyes" = "xyes"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME), libcurl-devel found at $LIBCURL_HOME)" + $as_echo "yes ($CLAMAV_MILTER_LIBS)" elif test "xyes" = "x"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME), libcurl-devel found at $LIBCURL_HOME)" + $as_echo "yes ($CLAMAV_MILTER_LIBS)" else - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME), libcurl-devel found at $LIBCURL_HOME) (yes)" + $as_echo "yes ($CLAMAV_MILTER_LIBS) (yes)" fi -else - if test "X$have_curl" != "Xyes" && test "X$have_json" != "Xyes"; then + else - $as_echo_n " clamsubmit : " + $as_echo_n " milter : " if test "xno" = "xno"; then : - $as_echo "no (missing libjson-c-dev AND libcurl-devel. Use the website to submit FPs/FNs.) (disabled)" + $as_echo "no (missing libmilter) (disabled)" elif test "xno" = "xyes"; then : - $as_echo "no (missing libjson-c-dev AND libcurl-devel. Use the website to submit FPs/FNs.)" + $as_echo "no (missing libmilter)" elif test "xno" = "x"; then : - $as_echo "no (missing libjson-c-dev AND libcurl-devel. Use the website to submit FPs/FNs.)" + $as_echo "no (missing libmilter)" else - $as_echo "no (missing libjson-c-dev AND libcurl-devel. Use the website to submit FPs/FNs.) (no)" + $as_echo "no (missing libmilter) (no)" +fi + + fi + + if test "X$have_json" = "Xyes"; then + + + $as_echo_n " clamsubmit : " + if test "xyes" = "xno"; then : + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking) (disabled)" +elif test "xyes" = "xyes"; then : + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)" +elif test "xyes" = "x"; then : + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)" +else + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking) (yes)" fi else - if test "X$have_curl" = "Xyes"; then $as_echo_n " clamsubmit : " @@ -35239,24 +36989,40 @@ $as_echo "no (missing libjson-c-dev. Use the website to submit FPs/FNs.) (no)" fi - else + fi + if test -z "$BUILD_CLAMONACC_TRUE"; then : - $as_echo_n " clamsubmit : " - if test "xno" = "xno"; then : - $as_echo "no (missing libcurl-devel. Use the website to submit FPs/FNs.) (disabled)" -elif test "xno" = "xyes"; then : - $as_echo "no (missing libcurl-devel. Use the website to submit FPs/FNs.)" -elif test "xno" = "x"; then : - $as_echo "no (missing libcurl-devel. Use the website to submit FPs/FNs.)" + + $as_echo_n " clamonacc : " + if test "x$enable_clamonacc" = "xno"; then : + $as_echo "yes (disabled)" +elif test "x$enable_clamonacc" = "xyes"; then : + $as_echo "yes" +elif test "x$enable_clamonacc" = "x"; then : + $as_echo "yes" else - $as_echo "no (missing libcurl-devel. Use the website to submit FPs/FNs.) (no)" + $as_echo "yes ($enable_clamonacc)" fi - fi - fi +else + + + $as_echo_n " clamonacc : " + if test "x$enable_clamonacc" = "xno"; then : + $as_echo "no (disabled)" +elif test "x$enable_clamonacc" = "xyes"; then : + $as_echo "no" +elif test "x$enable_clamonacc" = "x"; then : + $as_echo "no" +else + $as_echo "no ($enable_clamonacc)" fi +fi +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: Summary of engine performance features" >&5 $as_echo "$as_me: Summary of engine performance features" >&6;} if test "x$enable_debug" = "xyes"; then @@ -35353,6 +37119,19 @@ $as_echo "$as_me: Summary of engine detection features" >&6;} + $as_echo_n " iconv : " + if test "x" = "xno"; then : + $as_echo "$am_func_iconv (disabled)" +elif test "x" = "xyes"; then : + $as_echo "$am_func_iconv" +elif test "x" = "x"; then : + $as_echo "$am_func_iconv" +else + $as_echo "$am_func_iconv ()" +fi + + + $as_echo_n " bzip2 : " if test "x$want_bzip2" = "xno"; then : $as_echo "$bzip_check (disabled)" @@ -35364,19 +37143,35 @@ $as_echo "$bzip_check ($want_bzip2)" fi +if test "x${ZLIB_HOME}" != "x"; then $as_echo_n " zlib : " if test "xyes" = "xno"; then : - $as_echo "$ZLIB_HOME (disabled)" + $as_echo "yes (zlib found at $ZLIB_HOME) (disabled)" elif test "xyes" = "xyes"; then : - $as_echo "$ZLIB_HOME" + $as_echo "yes (zlib found at $ZLIB_HOME)" elif test "xyes" = "x"; then : - $as_echo "$ZLIB_HOME" + $as_echo "yes (zlib found at $ZLIB_HOME)" else - $as_echo "$ZLIB_HOME (yes)" + $as_echo "yes (zlib found at $ZLIB_HOME) (yes)" fi +else + + + $as_echo_n " zlib : " + if test "xyes" = "xno"; then : + $as_echo "yes (from system) (disabled)" +elif test "xyes" = "xyes"; then : + $as_echo "yes (from system)" +elif test "xyes" = "x"; then : + $as_echo "yes (from system)" +else + $as_echo "yes (from system) (yes)" +fi + +fi $as_echo_n " unrar : " @@ -35395,13 +37190,13 @@ $as_echo_n " preclass : " if test "xyes" = "xno"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME) (disabled)" + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking) (disabled)" elif test "xyes" = "xyes"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME)" + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)" elif test "xyes" = "x"; then : - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME)" + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)" else - $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME) (yes)" + $as_echo "yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking) (yes)" fi else @@ -35522,27 +37317,27 @@ # 4.0.x, and 4.1.0 are the known buggy versions # 3.4 doesn't have the bug if test "x$gcc_check" != "xyes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** Optimizations disabled to avoid compiler bugs ****** The resulting binaries will be slow! ****** It is recommended to either upgrade or downgrade your compiler -" >&5 + " >&5 $as_echo "$as_me: WARNING: ****** Optimizations disabled to avoid compiler bugs ****** The resulting binaries will be slow! ****** It is recommended to either upgrade or downgrade your compiler -" >&2;} + " >&2;} fi -if test "x$cross_compiling" != "xno" || test "x$gcc_check" != "xyes" || test "x$zlib_check" = "xno" || test "x$bzip_check" != "xok" ; then -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: +if test "x$cross_compiling" != "xno" || test "x$gcc_check" != "xyes" || test "x$bzip_check" != "xok" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ****** WARNING: ****** You are cross compiling to a different host or you are ****** linking to bugged system libraries or you have manually ****** disabled important configure checks. ****** Please be aware that this build may be badly broken. ****** DO NOT REPORT BUGS BASED ON THIS BUILD !!! -" >&5 + " >&5 $as_echo "$as_me: WARNING: ****** WARNING: ****** You are cross compiling to a different host or you are @@ -35550,6 +37345,20 @@ ****** disabled important configure checks. ****** Please be aware that this build may be badly broken. ****** DO NOT REPORT BUGS BASED ON THIS BUILD !!! -" >&2;} + " >&2;} fi +if test "X$have_json" = "Xyes" && test "x$json_linking" = "xdynamic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: +****** libjson-c is known to share symbol names with other JSON libraries +****** which may result in crashes for applications that use libclamav. +****** Consider using --with-libjson-static=path/to/libjson-c.a, +****** providing a json-c library that was compiled with CFLAGS=\"-fPIC\". + " >&5 +$as_echo "$as_me: WARNING: +****** libjson-c is known to share symbol names with other JSON libraries +****** which may result in crashes for applications that use libclamav. +****** Consider using --with-libjson-static=path/to/libjson-c.a, +****** providing a json-c library that was compiled with CFLAGS=\"-fPIC\". + " >&2;} +fi diff -Nru clamav-0.101.4+dfsg/configure.ac clamav-0.102.1+dfsg/configure.ac --- clamav-0.101.4+dfsg/configure.ac 2019-08-25 09:24:30.000000000 +0000 +++ clamav-0.102.1+dfsg/configure.ac 2019-11-24 12:55:15.000000000 +0000 @@ -1,7 +1,6 @@ dnl Copyright (C) 2013-2019 Cisco Systems, Inc. and/or its affiliates. All rights reserved. dnl Copyright (C) 2007-2013 Sourcefire, Inc. dnl Copyright (C) 2002-2007 Tomasz Kojm -dnl readdir_r checks (c) COPYRIGHT MIT 1995 dnl socklen_t check (c) Alexander V. Lukyanov dnl dnl This program is free software; you can redistribute it and/or modify @@ -20,16 +19,20 @@ dnl MA 02110-1301, USA. AC_PREREQ([2.59]) + dnl For a release change [devel] to the real version [0.xy] dnl also change VERSION below -AC_INIT([ClamAV], [0.101.4], [https://bugzilla.clamav.net/], [clamav], [https://www.clamav.net/]) +AC_INIT([ClamAV], [0.102.1], [https://bugzilla.clamav.net/], [clamav], [https://www.clamav.net/]) +dnl put configure auxiliary into config +AC_CONFIG_AUX_DIR([config]) + +dnl put configure auxiliary into config +AC_CONFIG_AUX_DIR([config]) dnl enable C++ AC_PROG_CXX() AH_BOTTOM([#include "platform.h"]) -dnl put configure auxiliary into config -AC_CONFIG_AUX_DIR([config]) AC_CONFIG_HEADERS([clamav-config.h ]) dnl safety check, this used to be a parameter to AC_INIT @@ -56,6 +59,8 @@ LTDL_INIT([recursive]) PKG_PROG_PKG_CONFIG(0.16) +m4_include([m4/reorganization/libclamav-only.m4]) + m4_include([m4/reorganization/build_tools.m4]) m4_include([m4/reorganization/headers.m4]) @@ -107,7 +112,7 @@ m4_include([m4/reorganization/code_checks/fanotify.m4]) m4_include([m4/reorganization/code_checks/setpgrp.m4]) m4_include([m4/reorganization/milter/enable.m4]) -m4_include([m4/reorganization/code_checks/iconv.m4]) +m4_include([m4/reorganization/libs/iconv_check.m4]) m4_include([m4/reorganization/code_checks/pthreads.m4]) m4_include([m4/reorganization/code_checks/reentrant.m4]) m4_include([m4/reorganization/utility_checks/id.m4]) @@ -125,7 +130,6 @@ m4_include([m4/reorganization/os_checks.m4]) m4_include([m4/reorganization/milter/check.m4]) m4_include([m4/reorganization/code_checks/pthread_02.m4]) -m4_include([m4/reorganization/code_checks/readdir.m4]) m4_include([m4/reorganization/code_checks/ctime.m4]) m4_include([m4/reorganization/code_checks/socklen_t.m4]) m4_include([m4/reorganization/clamav_user.m4]) @@ -140,10 +144,12 @@ m4_include([m4/reorganization/sha_collect.m4]) m4_include([m4/reorganization/yara.m4]) m4_include([m4/reorganization/code_checks/fts.m4]) -m4_include([m4/reorganization/libfreshclam.m4]) m4_include([m4/reorganization/prelude.m4]) m4_include([m4/reorganization/bsd.m4]) +dnl Clamonacc loading +m4_include([m4/reorganization/clamonacc.m4]) + dnl Freshclam dependencies m4_include([m4/reorganization/libs/curl.m4]) m4_include([m4/reorganization/substitutions.m4]) @@ -156,46 +162,80 @@ mspack_msg="External, $LIBMSPACK_CFLAGS $LIBMSPACK_LIBS" fi +dnl Enable Objective-C, needed for macOS, may not be inside conditional. +AC_PROG_OBJC + +dnl Detect the target system +build_linux=no +build_windows=no +build_mac=no + +AC_CANONICAL_HOST + +case "${host_os}" in + cygwin*|mingw*) + build_windows=yes + ;; + darwin*) + build_mac=yes + ;; + *) + build_linux=yes + ;; +esac + +AM_CONDITIONAL([LINUX], [test "$build_linux" = "yes"]) +AM_CONDITIONAL([WINDOWS], [test "$build_windows" = "yes"]) +AM_CONDITIONAL([MACOS], [test "$build_mac" = "yes"]) + + AC_CONFIG_FILES([ -clamscan/Makefile -database/Makefile -docs/Makefile -clamd/Makefile -clamd/clamav-daemon.service -clamd/clamav-daemon.socket -clamdscan/Makefile -clamsubmit/Makefile -clamav-milter/Makefile -freshclam/clamav-freshclam.service -freshclam/Makefile -sigtool/Makefile -clamconf/Makefile -etc/Makefile -test/Makefile -unit_tests/Makefile -fuzz/Makefile -clamdtop/Makefile -clambc/Makefile -libfreshclam/Makefile -Makefile -clamav-config -libclamav.pc -platform.h -docs/man/clamav-milter.8 -docs/man/clamav-milter.conf.5 -docs/man/clambc.1 -docs/man/clamconf.1 -docs/man/clamd.8 -docs/man/clamd.conf.5 -docs/man/clamdscan.1 -docs/man/clamscan.1 -docs/man/freshclam.1 -docs/man/freshclam.conf.5 -docs/man/sigtool.1 -docs/man/clamdtop.1 -docs/man/clamsubmit.1 -clamav-types.h -]) + Makefile + clamav-config + libclamav.pc + platform.h + clamav-types.h + clamav-version.h]) +if test "x$enable_libclamav_only" != "xyes"; then + AC_CONFIG_FILES([ + clamscan/Makefile + database/Makefile + docs/Makefile + clamd/Makefile + clamd/clamav-daemon.service + clamd/clamav-daemon.socket + clamdscan/Makefile + clamsubmit/Makefile + clamav-milter/Makefile + freshclam/clamav-freshclam.service + freshclam/Makefile + sigtool/Makefile + clamconf/Makefile + etc/Makefile + test/Makefile + unit_tests/Makefile + fuzz/Makefile + clamdtop/Makefile + clambc/Makefile + libfreshclam/Makefile + docs/man/clamav-milter.8 + docs/man/clamav-milter.conf.5 + docs/man/clambc.1 + docs/man/clamconf.1 + docs/man/clamd.8 + docs/man/clamd.conf.5 + docs/man/clamdscan.1 + docs/man/clamscan.1 + docs/man/freshclam.1 + docs/man/freshclam.conf.5 + docs/man/sigtool.1 + docs/man/clamdtop.1 + docs/man/clamsubmit.1 + ]) +fi + +AM_COND_IF([BUILD_CLAMONACC], + [AC_CONFIG_FILES([clamonacc/Makefile])]) # Define variables needed to generate clamav-types.h. m4_include([m4/reorganization/types.m4]) @@ -242,24 +282,36 @@ CL_MSG_STATUS([fdpassing ],[n/a],[]) fi CL_MSG_STATUS([IPv6 ],[$have_cv_ipv6],[$want_ipv6]) +CL_MSG_STATUS([openssl ],[$LIBSSL_HOME],[yes]) +CL_MSG_STATUS([libcurl ],[$LIBCURL_HOME],[yes]) -AC_MSG_NOTICE([Summary of optional tools]) -CL_MSG_STATUS([clamdtop ],[$CURSES_LIBS],[$enable_clamdtop]) -CL_MSG_STATUS([milter ],[yes],[$have_milter]) -if test "X$have_curl" = "Xyes" && test "X$have_json" = "Xyes"; then - CL_MSG_STATUS([clamsubmit ], [yes (libjson-c-dev found at $LIBJSON_HOME), libcurl-devel found at $LIBCURL_HOME)], [yes]) -else - if test "X$have_curl" != "Xyes" && test "X$have_json" != "Xyes"; then - CL_MSG_STATUS([clamsubmit ], [no (missing libjson-c-dev AND libcurl-devel. Use the website to submit FPs/FNs.)], [no]) +if test "x$enable_libclamav_only" != "xyes"; then + AC_MSG_NOTICE([Summary of optional tools]) + + if test "X$HAVE_LIBNCURSES" = "Xyes" || test "X$HAVE_LIBPDCURSES" = "Xyes"; then + CL_MSG_STATUS([clamdtop ],[yes ($CURSES_LIBS)], [yes]) + else + CL_MSG_STATUS([clamdtop ],[no (missing ncurses / pdcurses)], [no]) + fi + + if test "X$have_milter" = "Xyes"; then + CL_MSG_STATUS([milter ],[yes ($CLAMAV_MILTER_LIBS)], [yes]) + else + CL_MSG_STATUS([milter ],[no (missing libmilter)], [no]) + fi + + if test "X$have_json" = "Xyes"; then + CL_MSG_STATUS([clamsubmit ], [yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)], [yes]) else - if test "X$have_curl" = "Xyes"; then - CL_MSG_STATUS([clamsubmit ], [no (missing libjson-c-dev. Use the website to submit FPs/FNs.)], [no]) - else - CL_MSG_STATUS([clamsubmit ], [no (missing libcurl-devel. Use the website to submit FPs/FNs.)], [no]) - fi + CL_MSG_STATUS([clamsubmit ], [no (missing libjson-c-dev. Use the website to submit FPs/FNs.)], [no]) fi + + AM_COND_IF([BUILD_CLAMONACC], + [CL_MSG_STATUS([clamonacc ],[yes],[$enable_clamonacc])], + [CL_MSG_STATUS([clamonacc ],[no],[$enable_clamonacc])]) fi + AC_MSG_NOTICE([Summary of engine performance features]) if test "x$enable_debug" = "xyes"; then CL_MSG_STATUS([release mode],[no],[debug build]) @@ -280,11 +332,16 @@ CL_MSG_STATUS([mempool ],[$have_mempool],[$enable_mempool]) AC_MSG_NOTICE([Summary of engine detection features]) +CL_MSG_STATUS([iconv ],[$am_func_iconv],[]) CL_MSG_STATUS([bzip2 ],[$bzip_check],[$want_bzip2]) -CL_MSG_STATUS([zlib ],[$ZLIB_HOME],[yes]) +if test "x${ZLIB_HOME}" != "x"; then + CL_MSG_STATUS([zlib ], [yes (zlib found at $ZLIB_HOME)], [yes]) +else + CL_MSG_STATUS([zlib ], [yes (from system)], [yes]) +fi CL_MSG_STATUS([unrar ],[$want_unrar],[$want_unrar]) if test "X$have_json" = "Xyes"; then - CL_MSG_STATUS([preclass ],[yes (libjson-c-dev found at $LIBJSON_HOME)],[yes]) + CL_MSG_STATUS([preclass ],[yes (libjson-c-dev found at $LIBJSON_HOME, linking=$json_linking)],[yes]) else CL_MSG_STATUS([preclass ],[no (missing libjson-c-dev)],[no]) fi @@ -307,21 +364,29 @@ # 4.0.x, and 4.1.0 are the known buggy versions # 3.4 doesn't have the bug if test "x$gcc_check" != "xyes"; then - AC_MSG_WARN([ + AC_MSG_WARN([ ****** Optimizations disabled to avoid compiler bugs ****** The resulting binaries will be slow! ****** It is recommended to either upgrade or downgrade your compiler -]) + ]) fi -if test "x$cross_compiling" != "xno" || test "x$gcc_check" != "xyes" || test "x$zlib_check" = "xno" || test "x$bzip_check" != "xok" ; then -AC_MSG_WARN([ +if test "x$cross_compiling" != "xno" || test "x$gcc_check" != "xyes" || test "x$bzip_check" != "xok" ; then + AC_MSG_WARN([ ****** WARNING: ****** You are cross compiling to a different host or you are ****** linking to bugged system libraries or you have manually ****** disabled important configure checks. ****** Please be aware that this build may be badly broken. ****** DO NOT REPORT BUGS BASED ON THIS BUILD !!! -]) + ]) fi +if test "X$have_json" = "Xyes" && test "x$json_linking" = "xdynamic"; then + AC_MSG_WARN([ +****** libjson-c is known to share symbol names with other JSON libraries +****** which may result in crashes for applications that use libclamav. +****** Consider using --with-libjson-static=[path/to/libjson-c.a], +****** providing a json-c library that was compiled with CFLAGS="-fPIC". + ]) +fi diff -Nru clamav-0.101.4+dfsg/database/Makefile.in clamav-0.102.1+dfsg/database/Makefile.in --- clamav-0.101.4+dfsg/database/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/database/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -35,7 +35,17 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -100,7 +110,6 @@ host_triplet = @host@ target_triplet = @target@ subdir = database -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -113,6 +122,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -137,7 +147,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -155,7 +166,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -171,9 +181,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -181,6 +191,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -206,6 +217,7 @@ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -239,12 +251,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -276,8 +293,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -307,7 +322,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -328,6 +347,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -340,6 +360,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -351,6 +374,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -382,6 +406,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -390,6 +416,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -402,6 +429,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -431,6 +459,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -446,6 +475,7 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +xmlconfig = @xmlconfig@ EXTRA_DIST = main.cvd daily.cvd DBINST = @DBDIR@ all: all-am @@ -463,7 +493,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign database/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign database/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -639,6 +668,8 @@ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am +.PRECIOUS: Makefile + install-data-local: @test -s $(srcdir)/main.cvd -a -s $(srcdir)/daily.cvd || exit 0;\ diff -Nru clamav-0.101.4+dfsg/debian/.git-dpm clamav-0.102.1+dfsg/debian/.git-dpm --- clamav-0.101.4+dfsg/debian/.git-dpm 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/.git-dpm 2019-12-23 20:01:32.000000000 +0000 @@ -1,8 +1,8 @@ # see git-dpm(1) from git-dpm package -d270e1b7719040d02da3674f913a229a27a95ef8 -d270e1b7719040d02da3674f913a229a27a95ef8 -2ef384b1d0316b03c71b17de219c056c19169197 -2ef384b1d0316b03c71b17de219c056c19169197 -clamav_0.101.4+dfsg.orig.tar.xz -ae609c30ebf523a2f5e1b5f3cf25332cbb48686d -4975416 +44acef5309792ffe5a19646af6d6de9eb144d146 +44acef5309792ffe5a19646af6d6de9eb144d146 +9d46c747277c24c1b154649217ed802bfc8e35d0 +9d46c747277c24c1b154649217ed802bfc8e35d0 +clamav_0.102.1+dfsg.orig.tar.xz +0fcdd60421237e36155e611337b67374b2abc9a8 +5025796 diff -Nru clamav-0.101.4+dfsg/debian/changelog clamav-0.102.1+dfsg/debian/changelog --- clamav-0.101.4+dfsg/debian/changelog 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/changelog 2019-12-23 20:04:45.000000000 +0000 @@ -1,3 +1,16 @@ +clamav (0.102.1+dfsg-0+deb10u1) buster; urgency=medium + + * Import 0.102.1 (Closes: #945265) + - CVE-2019-15961 (A Denial-of-Service as a result of excessively long scan + times). + - Let freshclam show progress during download (Closes: #690789). + * Update symbol file. + * Add libfreshclam to the libclamav9 package. + * Add the clamonacc binary to the clamav-daemon package. + * Drop ScanOnAccess option. The clamonacc provides this functionality. + + -- Sebastian Andrzej Siewior Mon, 23 Dec 2019 21:04:45 +0100 + clamav (0.101.4+dfsg-0+deb10u1) buster; urgency=medium * Import 0.101.4 diff -Nru clamav-0.101.4+dfsg/debian/clamav-daemon.config.in clamav-0.102.1+dfsg/debian/clamav-daemon.config.in --- clamav-0.101.4+dfsg/debian/clamav-daemon.config.in 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-daemon.config.in 2019-12-23 20:01:56.000000000 +0000 @@ -72,7 +72,6 @@ set_debconf_value daemon LogFile set_debconf_value daemon LogTime set_debconf_value daemon LogRotate -set_debconf_value daemon ScanOnAccess set_debconf_value daemon OnAccessMaxFileSize set_debconf_value daemon AllowAllMatchScan set_debconf_value daemon ForceToDisk @@ -327,13 +326,10 @@ StateGeneric low clamav-daemon/LogTime LogRotate LogFile ;; "LogRotate") - StateGeneric low clamav-daemon/LogRotate ScanOnAccess LogFile - ;; - "ScanOnAccess") - StateGeneric low clamav-daemon/ScanOnAccess OnAccessMaxFileSize LogFile + StateGeneric low clamav-daemon/LogRotate LogFile ;; "OnAccessMaxFileSize") - StateGeneric low clamav-daemon/OnAccessMaxFileSize AllowAllMatchScan ScanOnAccess + StateGeneric low clamav-daemon/OnAccessMaxFileSize AllowAllMatchScan ;; "AllowAllMatchScan") StateGeneric low clamav-daemon/AllowAllMatchScan ForceToDisk OnAccessMaxFileSize diff -Nru clamav-0.101.4+dfsg/debian/clamav-daemon.install clamav-0.102.1+dfsg/debian/clamav-daemon.install --- clamav-0.101.4+dfsg/debian/clamav-daemon.install 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-daemon.install 2019-12-23 20:02:11.000000000 +0000 @@ -2,5 +2,6 @@ debian/tmp/lib/systemd/system/clamav-daemon.service debian/tmp/usr/bin/clamconf debian/tmp/usr/bin/clamdtop +debian/tmp/usr/bin/clamonacc debian/tmp/usr/sbin/clamd debian/usr.sbin.clamd etc/apparmor.d/ diff -Nru clamav-0.101.4+dfsg/debian/clamav-daemon.postinst.in clamav-0.102.1+dfsg/debian/clamav-daemon.postinst.in --- clamav-0.101.4+dfsg/debian/clamav-daemon.postinst.in 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-daemon.postinst.in 2019-12-23 20:01:56.000000000 +0000 @@ -116,12 +116,8 @@ db_get clamav-daemon/BytecodeTimeout || true BytecodeTimeout="$RET" fi - db_get clamav-daemon/ScanOnAccess || true - ScanOnAccess="$RET" - if [ "$ScanOnAccess" = "true" ]; then - db_get clamav-daemon/OnAccessMaxFileSize || true - OnAccessMaxFileSize="$RET" - fi + db_get clamav-daemon/OnAccessMaxFileSize || true + OnAccessMaxFileSize="$RET" db_get clamav-daemon/AllowAllMatchScan || true AllowAllMatchScan="$RET" db_get clamav-daemon/ForceToDisk || true @@ -148,8 +144,6 @@ # Use the defaults instead of the bogus values created by that versions. db_metaget clamav-daemon/LogRotate default || true LogRotate="$RET" - db_metaget clamav-daemon/ScanOnAccess default || true - ScanOnAccess="$RET" OnAccessMaxFileSize="" OnAccessIncludePath="" OnAccessExcludePath="" @@ -327,7 +321,6 @@ MaxQueue $MaxQueue ExtendedDetectionInfo $ExtendedDetectionInfo OLE2BlockMacros $OLE2BlockMacros -ScanOnAccess $ScanOnAccess AllowAllMatchScan $AllowAllMatchScan ForceToDisk $ForceToDisk DisableCertCheck $DisableCertCheck @@ -411,6 +404,10 @@ [ -n "$OnAccessDisableDDD" ] && echo "OnAccessDisableDDD $OnAccessDisableDDD" >> $DEBCONFFILE [ -n "$OnAccessPrevention" ] && echo "OnAccessPrevention $OnAccessPrevention" >> $DEBCONFFILE [ -n "$OnAccessExtraScanning" ] && echo "OnAccessExtraScanning $OnAccessExtraScanning" >> $DEBCONFFILE + [ -n "$OnAccessMaxThreads" ] && echo "OnAccessMaxThreads $OnAccessMaxThreads" >> $DEBCONFFILE + [ -n "$OnAccessDenyOnError" ] && echo "OnAccessDenyOnError $OnAccessDenyOnError" >> $DEBCONFFILE + [ -n "$OnAccessExcludeUname" ] && echo "OnAccessExcludeUname $OnAccessExcludeUname" >> $DEBCONFFILE + [ -n "$OnAccessRetryAttempts" ] && echo "OnAccessRetryAttempts $OnAccessRetryAttempts" >> $DEBCONFFILE [ -n "$HeuristicAlerts" ] && echo "HeuristicAlerts $HeuristicAlerts" >> $DEBCONFFILE [ -n "$AlertBrokenExecutables" ] && echo "AlertBrokenExecutables $AlertBrokenExecutables" >> $DEBCONFFILE [ -n "$AlertEncrypted" ] && echo "AlertEncrypted $AlertEncrypted" >> $DEBCONFFILE diff -Nru clamav-0.101.4+dfsg/debian/clamav-daemon.templates clamav-0.102.1+dfsg/debian/clamav-daemon.templates --- clamav-0.101.4+dfsg/debian/clamav-daemon.templates 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-daemon.templates 2019-12-23 20:01:56.000000000 +0000 @@ -143,11 +143,6 @@ Default: true _Description: Do you want to enable log rotation? -Template: clamav-daemon/ScanOnAccess -Type: boolean -Default: false -_Description: Do you want to enable on-access scanning? - Template: clamav-daemon/OnAccessMaxFileSize Type: string Default: 5M diff -Nru clamav-0.101.4+dfsg/debian/clamav-docs.doc-base clamav-0.102.1+dfsg/debian/clamav-docs.doc-base --- clamav-0.101.4+dfsg/debian/clamav-docs.doc-base 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-docs.doc-base 2019-12-10 20:41:31.000000000 +0000 @@ -7,7 +7,3 @@ Format: HTML Index: /usr/share/doc/clamav-docs/html/UserManual.html Files: /usr/share/doc/clamav-docs/html/UserManual/*.html - -Format: Text -Index: /usr/share/doc/clamav-docs/UserManual.md -Files: /usr/share/doc/clamav-docs/UserManual/*.md diff -Nru clamav-0.101.4+dfsg/debian/clamav-docs.docs clamav-0.102.1+dfsg/debian/clamav-docs.docs --- clamav-0.101.4+dfsg/debian/clamav-docs.docs 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-docs.docs 2019-12-10 20:41:31.000000000 +0000 @@ -1,7 +1,5 @@ debian/NEWS.Debian debian/README.Debian docs/html -docs/UserManual -docs/UserManual.md NEWS.md README.md diff -Nru clamav-0.101.4+dfsg/debian/clamav-freshclam.postinst.in clamav-0.102.1+dfsg/debian/clamav-freshclam.postinst.in --- clamav-0.101.4+dfsg/debian/clamav-freshclam.postinst.in 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/clamav-freshclam.postinst.in 2019-12-23 20:01:32.000000000 +0000 @@ -290,6 +290,7 @@ [ -n "$OnErrorExecute" ] && echo "OnErrorExecute $OnErrorExecute" >> $DEBCONFFILE [ -n "$LocalIPAddress" ] && echo "LocalIPAddress $LocalIPAddress" >> $DEBCONFFILE [ -n "$PrivateMirror" ] && echo "PrivateMirror $PrivateMirror" >> $DEBCONFFILE + [ -n "$ExcludeDatabase" ] && echo "ExcludeDatabase $ExcludeDatabase" >> $DEBCONFFILE if [ -n "$DatabaseCustomURL" ]; then for i in $DatabaseCustomURL; do echo "DatabaseCustomURL $i" >> $DEBCONFFILE diff -Nru clamav-0.101.4+dfsg/debian/libclamav9.install clamav-0.102.1+dfsg/debian/libclamav9.install --- clamav-0.101.4+dfsg/debian/libclamav9.install 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/libclamav9.install 2019-12-10 20:41:31.000000000 +0000 @@ -1 +1,2 @@ debian/tmp/usr/lib/*/libclamav.so.9* +debian/tmp/usr/lib/*/libfreshclam.so.2* diff -Nru clamav-0.101.4+dfsg/debian/libclamav9.symbols clamav-0.102.1+dfsg/debian/libclamav9.symbols --- clamav-0.101.4+dfsg/debian/libclamav9.symbols 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/libclamav9.symbols 2019-12-21 19:55:50.000000000 +0000 @@ -1,16 +1,20 @@ libclamav.so.9 libclamav9 #MINVER# * Build-Depends-Package: libclamav-dev - CLAMAV_PRIVATE@CLAMAV_PRIVATE 0.101.4 + CLAMAV_PRIVATE@CLAMAV_PRIVATE 0.102.1 CLAMAV_PUBLIC@CLAMAV_PUBLIC 0.101.0 - base64Flush@CLAMAV_PRIVATE 0.101.4 - blobAddData@CLAMAV_PRIVATE 0.101.4 - blobCreate@CLAMAV_PRIVATE 0.101.4 - blobDestroy@CLAMAV_PRIVATE 0.101.4 - cl_ASN1_GetTimeT@CLAMAV_PRIVATE 0.101.4 + __cli_strcasestr@CLAMAV_PRIVATE 0.102.1 + __cli_strndup@CLAMAV_PRIVATE 0.102.1 + __cli_strnlen@CLAMAV_PRIVATE 0.102.1 + __cli_strnstr@CLAMAV_PRIVATE 0.102.1 + base64Flush@CLAMAV_PRIVATE 0.102.1 + blobAddData@CLAMAV_PRIVATE 0.102.1 + blobCreate@CLAMAV_PRIVATE 0.102.1 + blobDestroy@CLAMAV_PRIVATE 0.102.1 + cl_ASN1_GetTimeT@CLAMAV_PRIVATE 0.102.1 cl_always_gen_section_hash@CLAMAV_PUBLIC 0.101.0 - cl_base64_decode@CLAMAV_PRIVATE 0.101.4 - cl_base64_encode@CLAMAV_PRIVATE 0.101.4 - cl_cleanup_crypto@CLAMAV_PRIVATE 0.101.4 + cl_base64_decode@CLAMAV_PRIVATE 0.102.1 + cl_base64_encode@CLAMAV_PRIVATE 0.102.1 + cl_cleanup_crypto@CLAMAV_PRIVATE 0.102.1 cl_countsigs@CLAMAV_PUBLIC 0.101.0 cl_cvdfree@CLAMAV_PUBLIC 0.101.0 cl_cvdhead@CLAMAV_PUBLIC 0.101.0 @@ -50,21 +54,21 @@ cl_fmap_close@CLAMAV_PUBLIC 0.101.0 cl_fmap_open_handle@CLAMAV_PUBLIC 0.101.0 cl_fmap_open_memory@CLAMAV_PUBLIC 0.101.0 - cl_get_pkey_file@CLAMAV_PRIVATE 0.101.4 - cl_get_x509_from_mem@CLAMAV_PRIVATE 0.101.4 - cl_hash_data@CLAMAV_PRIVATE 0.101.4 + cl_get_pkey_file@CLAMAV_PRIVATE 0.102.1 + cl_get_x509_from_mem@CLAMAV_PRIVATE 0.102.1 + cl_hash_data@CLAMAV_PRIVATE 0.102.1 cl_hash_destroy@CLAMAV_PUBLIC 0.101.0 - cl_hash_file_fd@CLAMAV_PRIVATE 0.101.4 - cl_hash_file_fd_ctx@CLAMAV_PRIVATE 0.101.4 - cl_hash_file_fp@CLAMAV_PRIVATE 0.101.4 + cl_hash_file_fd@CLAMAV_PRIVATE 0.102.1 + cl_hash_file_fd_ctx@CLAMAV_PRIVATE 0.102.1 + cl_hash_file_fp@CLAMAV_PRIVATE 0.102.1 cl_hash_init@CLAMAV_PUBLIC 0.101.0 cl_init@CLAMAV_PUBLIC 0.101.0 - cl_initialize_crypto@CLAMAV_PRIVATE 0.101.4 + cl_initialize_crypto@CLAMAV_PRIVATE 0.102.1 cl_load@CLAMAV_PUBLIC 0.101.0 - cl_load_cert@CLAMAV_PRIVATE 0.101.4 - cl_load_crl@CLAMAV_PRIVATE 0.101.4 + cl_load_cert@CLAMAV_PRIVATE 0.102.1 + cl_load_crl@CLAMAV_PRIVATE 0.102.1 cl_retdbdir@CLAMAV_PUBLIC 0.101.0 - cl_retflevel@CLAMAV_PUBLIC 0.101.4 + cl_retflevel@CLAMAV_PUBLIC 0.102.1 cl_retver@CLAMAV_PUBLIC 0.101.0 cl_scandesc@CLAMAV_PUBLIC 0.101.0 cl_scandesc_callback@CLAMAV_PUBLIC 0.101.0 @@ -72,184 +76,213 @@ cl_scanfile_callback@CLAMAV_PUBLIC 0.101.0 cl_scanmap_callback@CLAMAV_PUBLIC 0.101.0 cl_set_clcb_msg@CLAMAV_PUBLIC 0.101.0 - cl_sha1@CLAMAV_PRIVATE 0.101.4 - cl_sha256@CLAMAV_PRIVATE 0.101.4 - cl_sign_data@CLAMAV_PRIVATE 0.101.4 - cl_sign_data_keyfile@CLAMAV_PRIVATE 0.101.4 - cl_sign_file_fd@CLAMAV_PRIVATE 0.101.4 - cl_sign_file_fp@CLAMAV_PRIVATE 0.101.4 + cl_sha1@CLAMAV_PRIVATE 0.102.1 + cl_sha256@CLAMAV_PRIVATE 0.102.1 + cl_sign_data@CLAMAV_PRIVATE 0.102.1 + cl_sign_data_keyfile@CLAMAV_PRIVATE 0.102.1 + cl_sign_file_fd@CLAMAV_PRIVATE 0.102.1 + cl_sign_file_fp@CLAMAV_PRIVATE 0.102.1 cl_statchkdir@CLAMAV_PUBLIC 0.101.0 cl_statfree@CLAMAV_PUBLIC 0.101.0 cl_statinidir@CLAMAV_PUBLIC 0.101.0 cl_strerror@CLAMAV_PUBLIC 0.101.0 cl_update_hash@CLAMAV_PUBLIC 0.101.0 - cl_validate_certificate_chain@CLAMAV_PRIVATE 0.101.4 - cl_validate_certificate_chain_ts_dir@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_fd@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_fd_x509@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_fd_x509_keyfile@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_hash@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_hash_x509@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_hash_x509_keyfile@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_x509@CLAMAV_PRIVATE 0.101.4 - cl_verify_signature_x509_keyfile@CLAMAV_PRIVATE 0.101.4 - cli_ac_buildtrie@CLAMAV_PRIVATE 0.101.4 - cli_ac_chklsig@CLAMAV_PRIVATE 0.101.4 - cli_ac_free@CLAMAV_PRIVATE 0.101.4 - cli_ac_freedata@CLAMAV_PRIVATE 0.101.4 - cli_ac_init@CLAMAV_PRIVATE 0.101.4 - cli_ac_initdata@CLAMAV_PRIVATE 0.101.4 - cli_ac_scanbuff@CLAMAV_PRIVATE 0.101.4 - cli_bm_free@CLAMAV_PRIVATE 0.101.4 - cli_bm_init@CLAMAV_PRIVATE 0.101.4 - cli_bm_scanbuff@CLAMAV_PRIVATE 0.101.4 - cli_build_regex_list@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_alloc@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_clear@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_destroy@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_getresult_int@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_set_trace@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_setfile@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_setfuncid@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_setparam_int@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_context_setparam_ptr@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_debug@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_debug_printsrc@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_describe@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_destroy@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_done@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_init@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_load@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_prepare2@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_printversion@CLAMAV_PRIVATE 0.101.4 - cli_bytecode_run@CLAMAV_PRIVATE 0.101.4 - cli_bytefunc_describe@CLAMAV_PRIVATE 0.101.4 - cli_byteinst_describe@CLAMAV_PRIVATE 0.101.4 - cli_bytetype_describe@CLAMAV_PRIVATE 0.101.4 - cli_bytevalue_describe@CLAMAV_PRIVATE 0.101.4 - cli_calloc@CLAMAV_PRIVATE 0.101.4 - cli_checkfp_pe@CLAMAV_PRIVATE 0.101.4 - cli_chomp@CLAMAV_PRIVATE 0.101.4 - cli_ctime@CLAMAV_PRIVATE 0.101.4 - cli_cvdunpack@CLAMAV_PRIVATE 0.101.4 - cli_dbgmsg_internal@CLAMAV_PRIVATE 0.101.4 - cli_dconf_init@CLAMAV_PRIVATE 0.101.4 - cli_debug_flag@CLAMAV_PRIVATE 0.101.4 - cli_detect_environment@CLAMAV_PRIVATE 0.101.4 - cli_disasm_one@CLAMAV_PRIVATE 0.101.4 - cli_errmsg@CLAMAV_PRIVATE 0.101.4 - cli_filecopy@CLAMAV_PRIVATE 0.101.4 - cli_fmap_scandesc@CLAMAV_PRIVATE 0.101.4 - cli_free_vba_project@CLAMAV_PRIVATE 0.101.4 - cli_ftw@CLAMAV_PRIVATE 0.101.4 - cli_genhash_pe@CLAMAV_PRIVATE 0.101.4 - cli_gentemp@CLAMAV_PRIVATE 0.101.4 - cli_gentempfd@CLAMAV_PRIVATE 0.101.4 - cli_gettmpdir@CLAMAV_PRIVATE 0.101.4 - cli_hashfile@CLAMAV_PRIVATE 0.101.4 - cli_hashset_destroy@CLAMAV_PRIVATE 0.101.4 - cli_hashstream@CLAMAV_PRIVATE 0.101.4 - cli_hex2str@CLAMAV_PRIVATE 0.101.4 - cli_hex2ui@CLAMAV_PRIVATE 0.101.4 - cli_initroots@CLAMAV_PRIVATE 0.101.4 - cli_isnumber@CLAMAV_PRIVATE 0.101.4 - cli_js_destroy@CLAMAV_PRIVATE 0.101.4 - cli_js_init@CLAMAV_PRIVATE 0.101.4 - cli_js_output@CLAMAV_PRIVATE 0.101.4 - cli_js_parse_done@CLAMAV_PRIVATE 0.101.4 - cli_js_process_buffer@CLAMAV_PRIVATE 0.101.4 - cli_ldbtokenize@CLAMAV_PRIVATE 0.101.4 - cli_malloc@CLAMAV_PRIVATE 0.101.4 - cli_memstr@CLAMAV_PRIVATE 0.101.4 - cli_ole2_extract@CLAMAV_PRIVATE 0.101.4 - cli_parse_add@CLAMAV_PRIVATE 0.101.4 - cli_pcre_build@CLAMAV_PRIVATE 0.101.4 - cli_pcre_freeoff@CLAMAV_PRIVATE 0.101.4 - cli_pcre_init@CLAMAV_PRIVATE 0.101.4 - cli_pcre_perf_events_destroy@CLAMAV_PRIVATE 0.101.4 - cli_pcre_perf_print@CLAMAV_PRIVATE 0.101.4 - cli_pcre_recaloff@CLAMAV_PRIVATE 0.101.4 - cli_pcre_scanbuf@CLAMAV_PRIVATE 0.101.4 - cli_ppt_vba_read@CLAMAV_PRIVATE 0.101.4 - cli_printcxxver@CLAMAV_PRIVATE 0.101.4 - cli_readn@CLAMAV_PRIVATE 0.101.4 - cli_realloc@CLAMAV_PRIVATE 0.101.4 - cli_regcomp@CLAMAV_PRIVATE 0.101.4 - cli_regex2suffix@CLAMAV_PRIVATE 0.101.4 - cli_regexec@CLAMAV_PRIVATE 0.101.4 - cli_regfree@CLAMAV_PRIVATE 0.101.4 - cli_rmdirs@CLAMAV_PRIVATE 0.101.4 - cli_rndnum@CLAMAV_PRIVATE 0.101.4 - cli_sanitize_filepath@CLAMAV_PRIVATE 0.101.4 - cli_scanbuff@CLAMAV_PRIVATE 0.101.4 - cli_sigopts_handler@CLAMAV_PRIVATE 0.101.4 - cli_sigperf_events_destroy@CLAMAV_PRIVATE 0.101.4 - cli_sigperf_print@CLAMAV_PRIVATE 0.101.4 - cli_str2hex@CLAMAV_PRIVATE 0.101.4 - cli_strbcasestr@CLAMAV_PRIVATE 0.101.4 - cli_strdup@CLAMAV_PRIVATE 0.101.4 - cli_strerror@CLAMAV_PRIVATE 0.101.4 - cli_strlcat@CLAMAV_PRIVATE 0.101.4 - cli_strlcpy@CLAMAV_PRIVATE 0.101.4 - cli_strrcpy@CLAMAV_PRIVATE 0.101.4 - cli_strtok@CLAMAV_PRIVATE 0.101.4 - cli_strtokbuf@CLAMAV_PRIVATE 0.101.4 - cli_strtokenize@CLAMAV_PRIVATE 0.101.4 - cli_textbuffer_append_normalize@CLAMAV_PRIVATE 0.101.4 - cli_unescape@CLAMAV_PRIVATE 0.101.4 - cli_unlink@CLAMAV_PRIVATE 0.101.4 - cli_url_canon@CLAMAV_PRIVATE 0.101.4 - cli_utf16_to_utf8@CLAMAV_PRIVATE 0.101.4 - cli_utf16toascii@CLAMAV_PRIVATE 0.101.4 - cli_vba_inflate@CLAMAV_PRIVATE 0.101.4 - cli_vba_readdir@CLAMAV_PRIVATE 0.101.4 - cli_versig2@CLAMAV_PRIVATE 0.101.4 - cli_versig@CLAMAV_PRIVATE 0.101.4 - cli_warnmsg@CLAMAV_PRIVATE 0.101.4 - cli_wm_decrypt_macro@CLAMAV_PRIVATE 0.101.4 - cli_wm_readdir@CLAMAV_PRIVATE 0.101.4 - cli_writen@CLAMAV_PRIVATE 0.101.4 - decodeLine@CLAMAV_PRIVATE 0.101.4 - disasmbuf@CLAMAV_PRIVATE 0.101.4 - fmap@CLAMAV_PRIVATE 0.101.4 - get_fpu_endian@CLAMAV_PRIVATE 0.101.4 - have_clamjit@CLAMAV_PRIVATE 0.101.4 - have_rar@CLAMAV_PRIVATE 0.101.4 - html_normalise_map@CLAMAV_PRIVATE 0.101.4 - html_normalise_mem@CLAMAV_PRIVATE 0.101.4 - html_screnc_decode@CLAMAV_PRIVATE 0.101.4 - html_tag_arg_free@CLAMAV_PRIVATE 0.101.4 - init_domainlist@CLAMAV_PRIVATE 0.101.4 - init_regex_list@CLAMAV_PRIVATE 0.101.4 - init_whitelist@CLAMAV_PRIVATE 0.101.4 - is_regex_ok@CLAMAV_PRIVATE 0.101.4 - load_regex_matcher@CLAMAV_PRIVATE 0.101.4 + cl_validate_certificate_chain@CLAMAV_PRIVATE 0.102.1 + cl_validate_certificate_chain_ts_dir@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_fd@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_fd_x509@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_fd_x509_keyfile@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_hash@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_hash_x509@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_hash_x509_keyfile@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_x509@CLAMAV_PRIVATE 0.102.1 + cl_verify_signature_x509_keyfile@CLAMAV_PRIVATE 0.102.1 + cli_ac_buildtrie@CLAMAV_PRIVATE 0.102.1 + cli_ac_chklsig@CLAMAV_PRIVATE 0.102.1 + cli_ac_free@CLAMAV_PRIVATE 0.102.1 + cli_ac_freedata@CLAMAV_PRIVATE 0.102.1 + cli_ac_init@CLAMAV_PRIVATE 0.102.1 + cli_ac_initdata@CLAMAV_PRIVATE 0.102.1 + cli_ac_scanbuff@CLAMAV_PRIVATE 0.102.1 + cli_bm_free@CLAMAV_PRIVATE 0.102.1 + cli_bm_init@CLAMAV_PRIVATE 0.102.1 + cli_bm_scanbuff@CLAMAV_PRIVATE 0.102.1 + cli_build_regex_list@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_alloc@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_clear@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_destroy@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_getresult_int@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_set_trace@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_setfile@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_setfuncid@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_setparam_int@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_context_setparam_ptr@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_debug@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_debug_printsrc@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_describe@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_destroy@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_done@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_init@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_load@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_prepare2@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_printversion@CLAMAV_PRIVATE 0.102.1 + cli_bytecode_run@CLAMAV_PRIVATE 0.102.1 + cli_bytefunc_describe@CLAMAV_PRIVATE 0.102.1 + cli_byteinst_describe@CLAMAV_PRIVATE 0.102.1 + cli_bytetype_describe@CLAMAV_PRIVATE 0.102.1 + cli_bytevalue_describe@CLAMAV_PRIVATE 0.102.1 + cli_calloc@CLAMAV_PRIVATE 0.102.1 + cli_check_auth_header@CLAMAV_PRIVATE 0.102.1 + cli_chomp@CLAMAV_PRIVATE 0.102.1 + cli_ctime@CLAMAV_PRIVATE 0.102.1 + cli_cvdunpack@CLAMAV_PRIVATE 0.102.1 + cli_dbgmsg_internal@CLAMAV_PRIVATE 0.102.1 + cli_dconf_init@CLAMAV_PRIVATE 0.102.1 + cli_debug_flag@CLAMAV_PRIVATE 0.102.1 + cli_detect_environment@CLAMAV_PRIVATE 0.102.1 + cli_disasm_one@CLAMAV_PRIVATE 0.102.1 + cli_errmsg@CLAMAV_PRIVATE 0.102.1 + cli_filecopy@CLAMAV_PRIVATE 0.102.1 + cli_fmap_scandesc@CLAMAV_PRIVATE 0.102.1 + cli_free_vba_project@CLAMAV_PRIVATE 0.102.1 + cli_ftw@CLAMAV_PRIVATE 0.102.1 + cli_genhash_pe@CLAMAV_PRIVATE 0.102.1 + cli_gentemp@CLAMAV_PRIVATE 0.102.1 + cli_gentempfd@CLAMAV_PRIVATE 0.102.1 + cli_gettmpdir@CLAMAV_PRIVATE 0.102.1 + cli_hashfile@CLAMAV_PRIVATE 0.102.1 + cli_hashset_destroy@CLAMAV_PRIVATE 0.102.1 + cli_hashstream@CLAMAV_PRIVATE 0.102.1 + cli_hex2str@CLAMAV_PRIVATE 0.102.1 + cli_hex2ui@CLAMAV_PRIVATE 0.102.1 + cli_initroots@CLAMAV_PRIVATE 0.102.1 + cli_isnumber@CLAMAV_PRIVATE 0.102.1 + cli_js_destroy@CLAMAV_PRIVATE 0.102.1 + cli_js_init@CLAMAV_PRIVATE 0.102.1 + cli_js_output@CLAMAV_PRIVATE 0.102.1 + cli_js_parse_done@CLAMAV_PRIVATE 0.102.1 + cli_js_process_buffer@CLAMAV_PRIVATE 0.102.1 + cli_ldbtokenize@CLAMAV_PRIVATE 0.102.1 + cli_malloc@CLAMAV_PRIVATE 0.102.1 + cli_memstr@CLAMAV_PRIVATE 0.102.1 + cli_ole2_extract@CLAMAV_PRIVATE 0.102.1 + cli_parse_add@CLAMAV_PRIVATE 0.102.1 + cli_pcre_build@CLAMAV_PRIVATE 0.102.1 + cli_pcre_freeoff@CLAMAV_PRIVATE 0.102.1 + cli_pcre_init@CLAMAV_PRIVATE 0.102.1 + cli_pcre_perf_events_destroy@CLAMAV_PRIVATE 0.102.1 + cli_pcre_perf_print@CLAMAV_PRIVATE 0.102.1 + cli_pcre_recaloff@CLAMAV_PRIVATE 0.102.1 + cli_pcre_scanbuf@CLAMAV_PRIVATE 0.102.1 + cli_ppt_vba_read@CLAMAV_PRIVATE 0.102.1 + cli_printcxxver@CLAMAV_PRIVATE 0.102.1 + cli_readn@CLAMAV_PRIVATE 0.102.1 + cli_realloc@CLAMAV_PRIVATE 0.102.1 + cli_regcomp@CLAMAV_PRIVATE 0.102.1 + cli_regex2suffix@CLAMAV_PRIVATE 0.102.1 + cli_regexec@CLAMAV_PRIVATE 0.102.1 + cli_regfree@CLAMAV_PRIVATE 0.102.1 + cli_rmdirs@CLAMAV_PRIVATE 0.102.1 + cli_rndnum@CLAMAV_PRIVATE 0.102.1 + cli_sanitize_filepath@CLAMAV_PRIVATE 0.102.1 + cli_scanbuff@CLAMAV_PRIVATE 0.102.1 + cli_sigopts_handler@CLAMAV_PRIVATE 0.102.1 + cli_sigperf_events_destroy@CLAMAV_PRIVATE 0.102.1 + cli_sigperf_print@CLAMAV_PRIVATE 0.102.1 + cli_str2hex@CLAMAV_PRIVATE 0.102.1 + cli_strbcasestr@CLAMAV_PRIVATE 0.102.1 + cli_strdup@CLAMAV_PRIVATE 0.102.1 + cli_strerror@CLAMAV_PRIVATE 0.102.1 + cli_strlcat@CLAMAV_PRIVATE 0.102.1 + cli_strlcpy@CLAMAV_PRIVATE 0.102.1 + cli_strrcpy@CLAMAV_PRIVATE 0.102.1 + cli_strtok@CLAMAV_PRIVATE 0.102.1 + cli_strtokbuf@CLAMAV_PRIVATE 0.102.1 + cli_strtokenize@CLAMAV_PRIVATE 0.102.1 + cli_textbuffer_append_normalize@CLAMAV_PRIVATE 0.102.1 + cli_unescape@CLAMAV_PRIVATE 0.102.1 + cli_unlink@CLAMAV_PRIVATE 0.102.1 + cli_url_canon@CLAMAV_PRIVATE 0.102.1 + cli_utf16_to_utf8@CLAMAV_PRIVATE 0.102.1 + cli_utf16toascii@CLAMAV_PRIVATE 0.102.1 + cli_vba_inflate@CLAMAV_PRIVATE 0.102.1 + cli_vba_readdir@CLAMAV_PRIVATE 0.102.1 + cli_versig2@CLAMAV_PRIVATE 0.102.1 + cli_versig@CLAMAV_PRIVATE 0.102.1 + cli_warnmsg@CLAMAV_PRIVATE 0.102.1 + cli_wm_decrypt_macro@CLAMAV_PRIVATE 0.102.1 + cli_wm_readdir@CLAMAV_PRIVATE 0.102.1 + cli_writen@CLAMAV_PRIVATE 0.102.1 + decodeLine@CLAMAV_PRIVATE 0.102.1 + disasmbuf@CLAMAV_PRIVATE 0.102.1 + fmap@CLAMAV_PRIVATE 0.102.1 + get_fpu_endian@CLAMAV_PRIVATE 0.102.1 + have_clamjit@CLAMAV_PRIVATE 0.102.1 + have_rar@CLAMAV_PRIVATE 0.102.1 + html_normalise_map@CLAMAV_PRIVATE 0.102.1 + html_normalise_mem@CLAMAV_PRIVATE 0.102.1 + html_screnc_decode@CLAMAV_PRIVATE 0.102.1 + html_tag_arg_free@CLAMAV_PRIVATE 0.102.1 + init_domainlist@CLAMAV_PRIVATE 0.102.1 + init_regex_list@CLAMAV_PRIVATE 0.102.1 + init_whitelist@CLAMAV_PRIVATE 0.102.1 + is_regex_ok@CLAMAV_PRIVATE 0.102.1 + load_regex_matcher@CLAMAV_PRIVATE 0.102.1 lsig_sub_matched@CLAMAV_PUBLIC 0.101.0 - messageCreate@CLAMAV_PRIVATE 0.101.4 - messageDestroy@CLAMAV_PRIVATE 0.101.4 - mpool_calloc@CLAMAV_PRIVATE 0.101.4 - mpool_create@CLAMAV_PRIVATE 0.101.4 - mpool_destroy@CLAMAV_PRIVATE 0.101.4 - mpool_free@CLAMAV_PRIVATE 0.101.4 - mpool_getstats@CLAMAV_PRIVATE 0.101.4 - phishingScan@CLAMAV_PRIVATE 0.101.4 - phishing_done@CLAMAV_PRIVATE 0.101.4 - phishing_init@CLAMAV_PRIVATE 0.101.4 - regex_list_add_pattern@CLAMAV_PRIVATE 0.101.4 - regex_list_done@CLAMAV_PRIVATE 0.101.4 - regex_list_match@CLAMAV_PRIVATE 0.101.4 - tableCreate@CLAMAV_PRIVATE 0.101.4 - tableDestroy@CLAMAV_PRIVATE 0.101.4 - tableFind@CLAMAV_PRIVATE 0.101.4 - tableInsert@CLAMAV_PRIVATE 0.101.4 - tableIterate@CLAMAV_PRIVATE 0.101.4 - tableRemove@CLAMAV_PRIVATE 0.101.4 - tableUpdate@CLAMAV_PRIVATE 0.101.4 - text_normalize_init@CLAMAV_PRIVATE 0.101.4 - text_normalize_map@CLAMAV_PRIVATE 0.101.4 - text_normalize_reset@CLAMAV_PRIVATE 0.101.4 - uniq_add@CLAMAV_PRIVATE 0.101.4 - uniq_free@CLAMAV_PRIVATE 0.101.4 - uniq_get@CLAMAV_PRIVATE 0.101.4 - uniq_init@CLAMAV_PRIVATE 0.101.4 + messageCreate@CLAMAV_PRIVATE 0.102.1 + messageDestroy@CLAMAV_PRIVATE 0.102.1 + mpool_calloc@CLAMAV_PRIVATE 0.102.1 + mpool_create@CLAMAV_PRIVATE 0.102.1 + mpool_destroy@CLAMAV_PRIVATE 0.102.1 + mpool_free@CLAMAV_PRIVATE 0.102.1 + mpool_getstats@CLAMAV_PRIVATE 0.102.1 + phishingScan@CLAMAV_PRIVATE 0.102.1 + phishing_done@CLAMAV_PRIVATE 0.102.1 + phishing_init@CLAMAV_PRIVATE 0.102.1 + regex_list_add_pattern@CLAMAV_PRIVATE 0.102.1 + regex_list_done@CLAMAV_PRIVATE 0.102.1 + regex_list_match@CLAMAV_PRIVATE 0.102.1 + tableCreate@CLAMAV_PRIVATE 0.102.1 + tableDestroy@CLAMAV_PRIVATE 0.102.1 + tableFind@CLAMAV_PRIVATE 0.102.1 + tableInsert@CLAMAV_PRIVATE 0.102.1 + tableIterate@CLAMAV_PRIVATE 0.102.1 + tableRemove@CLAMAV_PRIVATE 0.102.1 + tableUpdate@CLAMAV_PRIVATE 0.102.1 + text_normalize_init@CLAMAV_PRIVATE 0.102.1 + text_normalize_map@CLAMAV_PRIVATE 0.102.1 + text_normalize_reset@CLAMAV_PRIVATE 0.102.1 + uniq_add@CLAMAV_PRIVATE 0.102.1 + uniq_free@CLAMAV_PRIVATE 0.102.1 + uniq_get@CLAMAV_PRIVATE 0.102.1 + uniq_init@CLAMAV_PRIVATE 0.102.1 +libfreshclam.so.2 libclamav9 #MINVER# + FRESHCLAM_PRIVATE@FRESHCLAM_PRIVATE 0.102.1 + FRESHCLAM_PUBLIC@FRESHCLAM_PUBLIC 0.102.1 + fc_cleanup@FRESHCLAM_PUBLIC 0.102.1 + fc_dns_query_update_info@FRESHCLAM_PUBLIC 0.102.1 + fc_download_url_database@FRESHCLAM_PUBLIC 0.102.1 + fc_download_url_databases@FRESHCLAM_PUBLIC 0.102.1 + fc_initialize@FRESHCLAM_PUBLIC 0.102.1 + fc_prune_database_directory@FRESHCLAM_PUBLIC 0.102.1 + fc_set_fccb_download_complete@FRESHCLAM_PUBLIC 0.102.1 + fc_strerror@FRESHCLAM_PUBLIC 0.102.1 + fc_test_database@FRESHCLAM_PUBLIC 0.102.1 + fc_update_database@FRESHCLAM_PUBLIC 0.102.1 + fc_update_databases@FRESHCLAM_PUBLIC 0.102.1 + logg@FRESHCLAM_PUBLIC 0.102.1 + logg_close@FRESHCLAM_PUBLIC 0.102.1 + logg_file@FRESHCLAM_PUBLIC 0.102.1 + logg_nowarn@FRESHCLAM_PUBLIC 0.102.1 + logg_rotate@FRESHCLAM_PUBLIC 0.102.1 + logg_size@FRESHCLAM_PUBLIC 0.102.1 + logg_time@FRESHCLAM_PUBLIC 0.102.1 + logg_verbose@FRESHCLAM_PUBLIC 0.102.1 + mprintf@FRESHCLAM_PUBLIC 0.102.1 + mprintf_disabled@FRESHCLAM_PUBLIC 0.102.1 + mprintf_nowarn@FRESHCLAM_PUBLIC 0.102.1 + mprintf_progress@FRESHCLAM_PUBLIC 0.102.1 + mprintf_quiet@FRESHCLAM_PUBLIC 0.102.1 + mprintf_stdout@FRESHCLAM_PUBLIC 0.102.1 + mprintf_verbose@FRESHCLAM_PUBLIC 0.102.1 diff -Nru clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.7.patch clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.7.patch --- clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.7.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.7.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From 35b9f66b69337557d4034f54d71e8ef61c32f295 Mon Sep 17 00:00:00 2001 +From a7c86edab3b79a492cee9b198550b8fc166cb6ba Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Fri, 14 Oct 2016 20:24:39 +0200 Subject: Add support for LLVM 3.7 diff -Nru clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.8.patch clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.8.patch --- clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.8.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.8.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From dadb4b37352a7ffcd3b4bc070281c858b34f1381 Mon Sep 17 00:00:00 2001 +From 95fdcec701fd627001204de47001f09f3f262cdc Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Fri, 14 Oct 2016 20:24:48 +0200 Subject: Add support for LLVM 3.8 diff -Nru clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.9.patch clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.9.patch --- clamav-0.101.4+dfsg/debian/patches/Add-support-for-LLVM-3.9.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/Add-support-for-LLVM-3.9.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From d270e1b7719040d02da3674f913a229a27a95ef8 Mon Sep 17 00:00:00 2001 +From 44acef5309792ffe5a19646af6d6de9eb144d146 Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Fri, 14 Oct 2016 20:24:56 +0200 Subject: Add support for LLVM 3.9 diff -Nru clamav-0.101.4+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch clamav-0.102.1+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch --- clamav-0.101.4+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/Change-paths-in-sample-conf-file-to-match-Debian.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From 4e4774ddaf9ce107b944830f11d33f9d539e6375 Mon Sep 17 00:00:00 2001 +From d9f52e3e525febad5ebb03918ec107fc516381c4 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Mon, 10 Mar 2014 19:20:18 -0400 Subject: Change paths in sample conf file to match Debian diff -Nru clamav-0.101.4+dfsg/debian/patches/add-support-for-system-tomsfastmath.patch clamav-0.102.1+dfsg/debian/patches/add-support-for-system-tomsfastmath.patch --- clamav-0.101.4+dfsg/debian/patches/add-support-for-system-tomsfastmath.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/add-support-for-system-tomsfastmath.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From b24dce89cbeab82baca41d02f21f7d8e3e642b3e Mon Sep 17 00:00:00 2001 +From 0ea69f1a20413dd0273659fba056ef20b4d64610 Mon Sep 17 00:00:00 2001 From: Andreas Cadhalpun Date: Wed, 11 Mar 2015 20:03:15 +0100 Subject: add support for system tomsfastmath @@ -14,10 +14,10 @@ create mode 100644 m4/reorganization/libs/tomsfastmath.m4 diff --git a/configure.ac b/configure.ac -index c0638fc..9a1cf02 100644 +index 4dc5d0f..0bcba7a 100644 --- a/configure.ac +++ b/configure.ac -@@ -96,6 +96,7 @@ m4_include([m4/reorganization/libs/libmspack.m4]) +@@ -101,6 +101,7 @@ m4_include([m4/reorganization/libs/libmspack.m4]) if test "x$use_internal_mspack" = "xno"; then mspack_msg="External, $LIBMSPACK_CFLAGS $LIBMSPACK_LIBS" fi @@ -25,7 +25,7 @@ AM_MAINTAINER_MODE m4_include([m4/reorganization/libs/libz.m4]) -@@ -302,6 +303,7 @@ fi +@@ -359,6 +360,7 @@ fi CL_MSG_STATUS([yara ],[$enable_yara],[$enable_yara]) CL_MSG_STATUS([fts ],[yes],[$lfs_fts_msg]) @@ -34,10 +34,10 @@ # Yep, downgrading the compiler avoids the bug too: # 4.0.x, and 4.1.0 are the known buggy versions diff --git a/libclamav/Makefile.am b/libclamav/Makefile.am -index 690d70b..fb58761 100644 +index e178d4b..88a0e60 100644 --- a/libclamav/Makefile.am +++ b/libclamav/Makefile.am -@@ -598,8 +598,10 @@ libclamav_la_SOURCES += yara_arena.c \ +@@ -602,8 +602,10 @@ libclamav_la_SOURCES += yara_arena.c \ yara_clam.h endif @@ -50,7 +50,7 @@ tomsfastmath/addsub/fp_add.c\ tomsfastmath/addsub/fp_add_d.c\ tomsfastmath/addsub/fp_addmod.c\ -@@ -681,6 +683,10 @@ libclamav_la_SOURCES += bignum.h\ +@@ -685,6 +687,10 @@ libclamav_la_SOURCES += bignum.h\ tomsfastmath/sqr/fp_sqr_comba_generic.c\ tomsfastmath/sqr/fp_sqr_comba_small_set.c\ tomsfastmath/sqr/fp_sqrmod.c @@ -62,7 +62,7 @@ .PHONY: version.h.tmp version.c: version.h diff --git a/libclamav/bignum.h b/libclamav/bignum.h -index 9acb17b..56967b1 100644 +index 8fdc956..56dfa95 100644 --- a/libclamav/bignum.h +++ b/libclamav/bignum.h @@ -1,9 +1,13 @@ @@ -79,9 +79,9 @@ + typedef fp_int mp_int; #define mp_cmp fp_cmp - #define mp_toradix_n(a,b,c,d) fp_toradix_n(a,b,c,d) + #define mp_toradix_n(a, b, c, d) fp_toradix_n(a, b, c, d) diff --git a/libclamav/xdp.c b/libclamav/xdp.c -index 8748b44..6e09ce4 100644 +index d5a4c4b..cc3b40d 100644 --- a/libclamav/xdp.c +++ b/libclamav/xdp.c @@ -52,7 +52,7 @@ diff -Nru clamav-0.101.4+dfsg/debian/patches/clamd_dont_depend_on_clamav_demon_socket.patch clamav-0.102.1+dfsg/debian/patches/clamd_dont_depend_on_clamav_demon_socket.patch --- clamav-0.101.4+dfsg/debian/patches/clamd_dont_depend_on_clamav_demon_socket.patch 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/patches/clamd_dont_depend_on_clamav_demon_socket.patch 2019-12-23 20:01:32.000000000 +0000 @@ -1,4 +1,4 @@ -From 75151a065b91b322e1d7867c0658686e316b2972 Mon Sep 17 00:00:00 2001 +From cf167ceaa82ad5cfc0176fade3a0d2286ff40554 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 11 Aug 2016 21:54:10 +0200 Subject: clamd: don't depend on clamav-demon.socket @@ -17,7 +17,7 @@ 1 file changed, 2 deletions(-) diff --git a/clamd/clamav-daemon.service.in b/clamd/clamav-daemon.service.in -index 0d12d8b..3943ce8 100644 +index 9a262c3..c13d72f 100644 --- a/clamd/clamav-daemon.service.in +++ b/clamd/clamav-daemon.service.in @@ -1,7 +1,6 @@ @@ -28,7 +28,7 @@ # Check for database existence ConditionPathExistsGlob=@DBDIR@/main.{c[vl]d,inc} ConditionPathExistsGlob=@DBDIR@/daily.{c[vl]d,inc} -@@ -14,4 +13,3 @@ StandardOutput=syslog +@@ -15,4 +14,3 @@ TimeoutStartSec=420 [Install] WantedBy=multi-user.target diff -Nru clamav-0.101.4+dfsg/debian/rules clamav-0.102.1+dfsg/debian/rules --- clamav-0.101.4+dfsg/debian/rules 2019-08-25 10:53:19.000000000 +0000 +++ clamav-0.102.1+dfsg/debian/rules 2019-12-21 19:55:50.000000000 +0000 @@ -88,7 +88,7 @@ fi;\ done; \ # Check for library features which may have been upgraded. - if ! grep -q "CL_FLEVEL 105" libclamav/others.h ; then \ + if ! grep -q "CL_FLEVEL 112" libclamav/others.h ; then \ echo "cl_retflevel needs boosting in symbol file"; \ touch debian/exit; \ fi; diff -Nru clamav-0.101.4+dfsg/docs/Makefile.am clamav-0.102.1+dfsg/docs/Makefile.am --- clamav-0.101.4+dfsg/docs/Makefile.am 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/Makefile.am 2019-11-20 04:42:24.000000000 +0000 @@ -18,7 +18,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. -EXTRA_DIST = html UserManual UserManual.md $(top_srcdir)/docs/man/*.in +EXTRA_DIST = html $(top_srcdir)/docs/man/*.in man_MANS = man/clamscan.1 man/freshclam.1 man/sigtool.1 man/clamd.8 man/clamd.conf.5 man/clamdscan.1 man/clamav-milter.8 man/clamav-milter.conf.5 man/freshclam.conf.5 man/clamconf.1 man/clamdtop.1 man/clambc.1 if ENABLE_CLAMSUBMIT diff -Nru clamav-0.101.4+dfsg/docs/Makefile.in clamav-0.102.1+dfsg/docs/Makefile.in --- clamav-0.101.4+dfsg/docs/Makefile.in 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/Makefile.in 2019-11-20 04:42:24.000000000 +0000 @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2013 Free Software Foundation, Inc. +# Copyright (C) 1994-2017 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -34,7 +34,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301, USA. VPATH = @srcdir@ -am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ @@ -100,7 +110,6 @@ target_triplet = @target@ @ENABLE_CLAMSUBMIT_TRUE@am__append_1 = man/clamsubmit.1 subdir = docs -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \ $(top_srcdir)/m4/ax_check_uname_syscall.m4 \ @@ -113,6 +122,7 @@ $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/mmap_private.m4 $(top_srcdir)/m4/resolv.m4 \ $(top_srcdir)/m4/reorganization/version.m4 \ + $(top_srcdir)/m4/reorganization/libclamav-only.m4 \ $(top_srcdir)/m4/reorganization/build_tools.m4 \ $(top_srcdir)/m4/reorganization/headers.m4 \ $(top_srcdir)/m4/reorganization/c_options.m4 \ @@ -137,7 +147,8 @@ $(top_srcdir)/m4/reorganization/code_checks/fanotify.m4 \ $(top_srcdir)/m4/reorganization/code_checks/setpgrp.m4 \ $(top_srcdir)/m4/reorganization/milter/enable.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/iconv.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv_check.m4 \ + $(top_srcdir)/m4/reorganization/libs/iconv.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthreads.m4 \ $(top_srcdir)/m4/reorganization/code_checks/reentrant.m4 \ $(top_srcdir)/m4/reorganization/utility_checks/id.m4 \ @@ -155,7 +166,6 @@ $(top_srcdir)/m4/reorganization/os_checks.m4 \ $(top_srcdir)/m4/reorganization/milter/check.m4 \ $(top_srcdir)/m4/reorganization/code_checks/pthread_02.m4 \ - $(top_srcdir)/m4/reorganization/code_checks/readdir.m4 \ $(top_srcdir)/m4/reorganization/code_checks/ctime.m4 \ $(top_srcdir)/m4/reorganization/code_checks/socklen_t.m4 \ $(top_srcdir)/m4/reorganization/clamav_user.m4 \ @@ -171,9 +181,9 @@ $(top_srcdir)/m4/reorganization/sha_collect.m4 \ $(top_srcdir)/m4/reorganization/yara.m4 \ $(top_srcdir)/m4/reorganization/code_checks/fts.m4 \ - $(top_srcdir)/m4/reorganization/libfreshclam.m4 \ $(top_srcdir)/m4/reorganization/prelude.m4 \ $(top_srcdir)/m4/reorganization/bsd.m4 \ + $(top_srcdir)/m4/reorganization/clamonacc.m4 \ $(top_srcdir)/m4/reorganization/libs/curl.m4 \ $(top_srcdir)/m4/reorganization/substitutions.m4 \ $(top_srcdir)/m4/reorganization/strni.m4 \ @@ -181,6 +191,7 @@ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/clamav-config.h \ $(top_builddir)/libclammspack/config.h @@ -240,6 +251,7 @@ NROFF = nroff MANS = $(man_MANS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ @@ -273,12 +285,17 @@ CLAMD_LIBS = @CLAMD_LIBS@ CLAMMEM_CPPFLAGS = @CLAMMEM_CPPFLAGS@ CLAMMEM_LIBS = @CLAMMEM_LIBS@ +CLAMONACC_CPPFLAGS = @CLAMONACC_CPPFLAGS@ +CLAMONACC_LIBS = @CLAMONACC_LIBS@ CLAMSCAN_CPPFLAGS = @CLAMSCAN_CPPFLAGS@ CLAMSCAN_LIBS = @CLAMSCAN_LIBS@ CLAMSUBMIT_CFLAGS = @CLAMSUBMIT_CFLAGS@ CLAMSUBMIT_LIBS = @CLAMSUBMIT_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CURL_CPPFLAGS = @CURL_CPPFLAGS@ +CURL_LDFLAGS = @CURL_LDFLAGS@ +CURL_LIBS = @CURL_LIBS@ CURSES_CPPFLAGS = @CURSES_CPPFLAGS@ CURSES_LIBS = @CURSES_LIBS@ CXX = @CXX@ @@ -310,8 +327,6 @@ GREP = @GREP@ HAVE_STRNI = @HAVE_STRNI@ HAVE_YARA = @HAVE_YARA@ -ICONV_CPPFLAGS = @ICONV_CPPFLAGS@ -ICONV_LDFLAGS = @ICONV_LDFLAGS@ INCLTDL = @INCLTDL@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ @@ -341,7 +356,11 @@ LIBCLAMAV_CPPFLAGS = @LIBCLAMAV_CPPFLAGS@ LIBCLAMAV_LIBS = @LIBCLAMAV_LIBS@ LIBCLAMAV_VERSION = @LIBCLAMAV_VERSION@ +LIBCLAMAV_VERSION_NUM = @LIBCLAMAV_VERSION_NUM@ LIBCLAMSHARED_CPPFLAGS = @LIBCLAMSHARED_CPPFLAGS@ +LIBFRESHCLAM_VERSION = @LIBFRESHCLAM_VERSION@ +LIBFRESHCLAM_VERSION_NUM = @LIBFRESHCLAM_VERSION_NUM@ +LIBICONV = @LIBICONV@ LIBLTDL = @LIBLTDL@ LIBM = @LIBM@ LIBMSPACK_CFLAGS = @LIBMSPACK_CFLAGS@ @@ -362,6 +381,7 @@ LTDLINCL = @LTDLINCL@ LTDLOPEN = @LTDLOPEN@ LTLIBBZ2 = @LTLIBBZ2@ +LTLIBICONV = @LTLIBICONV@ LTLIBOBJS = @LTLIBOBJS@ LT_ARGZ_H = @LT_ARGZ_H@ LT_CONFIG_H = @LT_CONFIG_H@ @@ -374,6 +394,9 @@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ +OBJC = @OBJC@ +OBJCDEPMODE = @OBJCDEPMODE@ +OBJCFLAGS = @OBJCFLAGS@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ @@ -385,6 +408,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKAGE_VERSION_NUM = @PACKAGE_VERSION_NUM@ PATH_SEPARATOR = @PATH_SEPARATOR@ PCRE_CPPFLAGS = @PCRE_CPPFLAGS@ PCRE_LIBS = @PCRE_LIBS@ @@ -416,6 +440,8 @@ XML_LIBS = @XML_LIBS@ YACC = @YACC@ YFLAGS = @YFLAGS@ +ZLIB_CFLAGS = @ZLIB_CFLAGS@ +ZLIB_LIBS = @ZLIB_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ @@ -424,6 +450,7 @@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +ac_ct_OBJC = @ac_ct_OBJC@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ @@ -436,6 +463,7 @@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ +curl_config = @curl_config@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -465,6 +493,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -480,7 +509,8 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -EXTRA_DIST = html UserManual UserManual.md $(top_srcdir)/docs/man/*.in +xmlconfig = @xmlconfig@ +EXTRA_DIST = html $(top_srcdir)/docs/man/*.in man_MANS = man/clamscan.1 man/freshclam.1 man/sigtool.1 man/clamd.8 \ man/clamd.conf.5 man/clamdscan.1 man/clamav-milter.8 \ man/clamav-milter.conf.5 man/freshclam.conf.5 man/clamconf.1 \ @@ -500,7 +530,6 @@ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -811,6 +840,8 @@ uninstall-am uninstall-man uninstall-man1 uninstall-man5 \ uninstall-man8 +.PRECIOUS: Makefile + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-Debian-Ubuntu.md clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Debian-Ubuntu.md --- clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-Debian-Ubuntu.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Debian-Ubuntu.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,313 +0,0 @@ -# Installation on Debian and Ubuntu Linux Distributions - -Below are the steps for installing ClamAV from source on Debian and Ubuntu Linux. - -## Install prerequisites - -1. Install ClamAV dependencies - 1. Install the developer tools - ```bash - sudo apt-get install build-essential - ``` - 2. Install library dependencies - ```bash - sudo apt-get install openssl libssl-dev libcurl4-openssl-dev zlib1g-dev libpng-dev libxml2-dev libjson-c-dev libbz2-dev libpcre3-dev ncurses-dev - ``` - 3. (very optional) Those wishing to use clamav-milter may wish to install the following - ```bash - sudo apt-get install libmilter1.0.1 libmilter-dev - ``` - -2. Install the unit testing dependencies - ```bash - sudo apt-get valgrind check - ``` - -_Note_: LLVM is also an optional dependency. LLVM will not provide any additional features, but is an alternative method for executing bytecode signatures versus using the built-in bytecode interpreter. Limited performance testing between LLVM and the bytecode interpreter did not yield conclusive evidence that one is "better" than the other. For the sake of simplicity, it is not recommended to install LLVM. - -## Download the latest stable release - -1. Open a browser and navigate to [the ClamAV downloads page](http://www.clamav.net/downloads) -2. Click `clamav-.tar.gz` link to download the latest stable release. - -## Extract the source archive - -```bash -cd ~/Downloads -tar xzf clamav-.tar.gz -cd clamav-.tar.gz -``` - -## Configure the build - -ClamAV's configure script should detect each of the above dependencies automatically. - -### Typical `./configure` usage - -```bash -./configure --enable-check -``` - -Once `./configure` completes, it will print a summary. Verify that the packages you installed are in fact being detected. - -Example configure summary output: - -```bash -configure: Summary of detected features follows - OS : linux-gnu - pthreads : yes (-lpthread) -configure: Summary of miscellaneous features - check : -lcheck_pic -pthread -lrt -lm -lsubunit - fanotify : yes - fdpassing : 1 - IPv6 : yes -configure: Summary of optional tools - clamdtop : -lncurses (auto) - milter : yes (disabled) - clamsubmit : yes (libjson-c-dev found at /usr), libcurl-devel found at /usr) -configure: Summary of engine performance features - release mode: yes - llvm : no (disabled) - mempool : yes -configure: Summary of engine detection features - bzip2 : ok - zlib : /usr - unrar : yes - preclass : yes (libjson-c-dev found at /usr) - pcre : /usr - libmspack : yes (Internal) - libxml2 : yes, from /usr - yara : yes - fts : yes (libc) - -``` - -### Additional popular `./configure` options - -* `--with-systemdsystemunitdir` - Do not install `systemd` socket files. This option disables systemd support, but will allow you to `make install` to a user-owned directory without requiring `sudo`/root privileges: - ```bash - ./configure --with-systemdsystemunitdir=no - ``` -* `--sysconfdir` - Install the configuration files to `/etc` instead of `/usr/local/etc`: - ```bash - ./configure -–sysconfdir=/etc - ``` -* `--prefix` - Install ClamAV to a directory other than `/usr/local/`: - * Example 1: Install to a local `./install` directory. - ```bash - ./configure --prefix=`pwd`/install - ``` - * Example 2: Install ClamAV locally on an unprivileged shell account. - ```bash - ./configure --prefix=$HOME/clamav --disable-clamav --with-systemdsystemunitdir=no - ``` -* `--disable-clamav` - _Don't_ drop super-user priveleges to run `freshclam` or `clamd` as the `clamav`* user. - ```bash - ./configure --disable-clamav - ``` - *_Tip_: Using this `--disable-clamav` means that `freshclam` and `clamd` will run with _root privleges_ if invoked using `sudo`. Running `clamd` or `clamscan` as root is **not recommended**. Instead of using this option, you can configure `freshclam` or `clamd` to drop to any other user by: - * setting the `DatabaseOwner` option in `freshclam.conf` and - * setting the `User` option in `clamd.conf`. - -Please see the `./configure --help` for additional options. - -### Compile ClamAV - -Compile ClamAV with: -```bash -make -j2 -``` - -### Run ClamAV Unit Tests (Optional) - -For peace of mind, it can be helpful to run a small suite of unit and system tests. - -Run: -```bash -make check -``` - -All tests should pass.* Output will look something like this: - -```bash. - ... -PASS: check_clamav -PASS: check_freshclam.sh -PASS: check_sigtool.sh -PASS: check_unit_vg.sh -PASS: check1_clamscan.sh -PASS: check2_clamd.sh -PASS: check3_clamd.sh -PASS: check4_clamd.sh -PASS: check5_clamd_vg.sh -PASS: check6_clamd_vg.sh -SKIP: check7_clamd_hg.sh -PASS: check8_clamd_hg.sh -PASS: check9_clamscan_vg.sh - ... -============================================================================ -Testsuite summary for ClamAV 0.100.2 -============================================================================ -# TOTAL: 13 -# PASS: 12 -# SKIP: 1 -# XFAIL: 0 -# FAIL: 0 -# XPASS: 0 -# ERROR: 0 -``` - -_Notes_: - -* The `*.vg.sh` tests will be skipped unless you run `make check VG=1`. -* The `check7_clamd.hg.sh` (helgrind) is presently disabled and will be skipped. - * For details, see: [the Git commit](https://github.com/Cisco-Talos/clamav-devel/commit/2a5d51809a56be9a777ded02969a7427a3c26713) - -If you have a failure or an error in the unit tests, it could be that you are missing one or more of the prerequisites. - -If you are investigating a failure, please do the following: - -`cd unit_tests` - -Use `less` to read the log for the failed test. -Example: - -```bash -less check4_clamd.sh.log` -``` - -To submit a bug report regarding unit text failures, please follow these [bug reporting steps](../Installation-Unix.md#Reporting-a-unit-test-failure-bug). - -### Install ClamAV - -Install ClamAV with: -```bash -make install -``` - -_Tip_: If installing to the default or other system-owned directory, you may need to use `sudo`. - -### First time set-up - -_Note_: The following instructions assume you used the default install paths (i.e. `/usr/local`). If you modified the install locations using `--prefix` or `--sysconfdir` options, replace `/usr/local` with your chosen install path. - -#### `freshclam` config - -Before you can use `freshclam` to download updates, you need to create a `freshclam` config. A sample config is provided for you. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/freshclam.conf.sample /usr/local/etc/freshclam.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogRotate` - * `NotifyClamd` - * `DatabaseOwner` - -3. Create the database directory. *Tip: _You may need to use `sudo`._ - ```bash - mkdir /usr/local/share/clamav - ``` - -#### `clamd` config (optional) - -You can run `clamscan` without setting the config options for `clamd`. However, the `clamd` scanning daemon allows you to use `clamdscan` to perform faster a-la-carte scans, allows you to run multi-threaded scans, and allows you to use `clamav-milter` if you want to use ClamAV as a mail filter if you host an email server. - -Additionally, if you are a running modern versions of Linux where the FANOTIFY kernel feature is enabled, `clamd` has a feature run with On-Access Scanning*. *When properly configured*, On-Access Scanning can scan files as they are accessed and optionally block access to the file in the event that a signature alerted. - - _Note_: At this time, for On-Access Scanning to work, `clamd` must run with `sudo`/root privileges. For more details, please see our documentation on On-Access Scanning. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/clamd.conf.sample /usr/local/etc/clamd.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - * You also _need_ to select a Socket option for `clamd` so `clamdscan` and other utilities can communicate with `clamd`. You must enable _one_ of the following. - * `LocalSocket` - * `TCPSocket` - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogClean` - * `LogRotate` - * `User` - * `ScanOnAccess` - * `OnAccessIncludePath` - * `OnAccessExcludePath` - * `OnAccessPrevention` - -#### Configure SELinux for ClamAV - -Certain distributions (notably RedHat variants) when operating with SELinux enabled use the non-standard `antivirus_can_scan_system` SELinux option instead of `clamd_can_scan_system`. - -At this time, libclamav only sets the `clamd_can_scan_system` option, so you may need to manually enable `antivirus_can_scan_system`. If you don't perform this step, freshclam will log something like this when it tests the newly downloaded signature databases: - -``` -During database load : LibClamAV Warning: RWX mapping denied: Can't allocate RWX Memory: Permission denied -``` - -To allow ClamAV to operate under SELinux, run the following: -```bash -setsebool -P antivirus_can_scan_system 1 -``` - -#### Download / Update the signature database - -Before you can run a scan, you'll need to download the signature databases. Once again, you may need to run with `sudo`/root privileges. - -If you installed to a location in your system PATH: -```bash -freshclam -``` - -If you installed to another location: -```bash -/////freshclam -``` - - _Important_: It is common on Ubuntu after a fresh install to see the following error the first time you use ClamAV: - ```bash - $ freshclam - freshclam: error while loading shared libraries: libclamav.so.7: cannot open shared object file: No such file or directory - ``` - - You can fix this error by using ldconfig to rebuild the library search path. - ```bash - sudo ldconfig - ``` - -#### Users and on user privileges - -If you are running `freshclam` and `clamd` as root or with `sudo`, and you did not explicitely configure with `--disable-clamav`, you will want to ensure that the `DatabaseOwner` user specified in `freshclam.conf` owns the database directory so it can download signature udpates. - -The user that `clamd`, `clamdscan`, and `clamscan` run as may be the same user, but if it isn't -- it merely needs _read_ access to the database directory. - -If you choose to use the default `clamav` user to run `freshclam` and `clamd`, you'll need to create the clamav group and the clamav user account the first time you install ClamAV. - -```bash -groupadd clamav -useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav -``` - -Finally, you will want to set user ownership of the database directory. -For example: -```bash -sudo chown -R clamav:clamav /usr/local/share/clamav -``` - -### Usage - -You should be all set up to run scans. - -Take a look at our [usage documentation](../Usage.md) to learn about how to use ClamAV each of the utilities. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-Redhat-CentOS.md clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Redhat-CentOS.md --- clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-Redhat-CentOS.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-Redhat-CentOS.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,302 +0,0 @@ -# Installation on Redhat and CentOS Linux Distributions - -Below are the steps for installing ClamAV from source on Redhat and CentOS Linux. - -## Install prerequisites - -1. Install ClamAV dependencies - 1. Install the developer tools - ```bash - sudo yum groupinstall "Development Tools" - ``` - 2. Install library dependencies - ```bash - sudo yum install openssl openssl-devel libcurl-devel zlib-devel libpng-devel libxml2-devel json-c-devel bzip2-devel pcre2-devel ncurses-devel - ``` - 3. (very optional) Those wishing to use clamav-milter may wish to install the following - ```bash - sudo yum install sendmail sendmail-devel - ``` - -2. Install the unit testing dependencies - ```bash - sudo yum valgrind check - ``` - -_Note_: LLVM is also an optional dependency. LLVM will not provide any additional features, but is an alternative method for executing bytecode signatures versus using the built-in bytecode interpreter. Limited performance testing between LLVM and the bytecode interpreter did not yield conclusive evidence that one is "better" than the other. For the sake of simplicity, it is not recommended to install LLVM. - -## Download the latest stable release - -1. Open a browser and navigate to [the ClamAV downloads page](http://www.clamav.net/downloads) -2. Click `clamav-.tar.gz` link to download the latest stable release. - -## Extract the source archive - -```bash -cd ~/Downloads -tar xzf clamav-.tar.gz -cd clamav-.tar.gz -``` - -## Configure the build - -ClamAV's configure script should detect each of the above dependencies automatically. - -### Typical `./configure` usage - -```bash -./configure --enable-check -``` - -Once `./configure` completes, it will print a summary. Verify that the packages you installed are in fact being detected. - -Example configure summary output: - -```bash -configure: Summary of detected features follows - OS : linux-gnu - pthreads : yes (-lpthread) -configure: Summary of miscellaneous features - check : -lcheck_pic -pthread -lrt -lm -lsubunit - fanotify : yes - fdpassing : 1 - IPv6 : yes -configure: Summary of optional tools - clamdtop : -lncurses (auto) - milter : yes (disabled) - clamsubmit : yes (libjson-c-dev found at /usr), libcurl-devel found at /usr) -configure: Summary of engine performance features - release mode: yes - llvm : no (disabled) - mempool : yes -configure: Summary of engine detection features - bzip2 : ok - zlib : /usr - unrar : yes - preclass : yes (libjson-c-dev found at /usr) - pcre : /usr - libmspack : yes (Internal) - libxml2 : yes, from /usr - yara : yes - fts : yes (libc) - -``` - -### Additional popular `./configure` options - -* `--with-systemdsystemunitdir` - Do not install `systemd` socket files. This option disables systemd support, but will allow you to `make install` to a user-owned directory without requiring `sudo`/root privileges: - ```bash - ./configure --with-systemdsystemunitdir=no - ``` -* `--sysconfdir` - Install the configuration files to `/etc` instead of `/usr/local/etc`: - ```bash - ./configure -–sysconfdir=/etc - ``` -* `--prefix` - Install ClamAV to a directory other than `/usr/local/`: - * Example 1: Install to a local `./install` directory. - ```bash - ./configure --prefix=`pwd`/install - ``` - * Example 2: Install ClamAV locally on an unprivileged shell account. - ```bash - ./configure --prefix=$HOME/clamav --disable-clamav --with-systemdsystemunitdir=no - ``` -* `--disable-clamav` - _Don't_ drop super-user priveleges to run `freshclam` or `clamd` as the `clamav`* user. - ```bash - ./configure --disable-clamav - ``` - *_Tip_: Using this `--disable-clamav` means that `freshclam` and `clamd` will run with _root privleges_ if invoked using `sudo`. Running `clamd` or `clamscan` as root is **not recommended**. Instead of using this option, you can configure `freshclam` or `clamd` to drop to any other user by: - * setting the `DatabaseOwner` option in `freshclam.conf` and - * setting the `User` option in `clamd.conf`. - -Please see the `./configure --help` for additional options. - -### Compile ClamAV - -Compile ClamAV with: -```bash -make -j2 -``` - -### Run ClamAV Unit Tests (Optional) - -For peace of mind, it can be helpful to run a small suite of unit and system tests. - -Run: -```bash -make check -``` - -All tests should pass.* Output will look something like this: - -```bash. - ... -PASS: check_clamav -PASS: check_freshclam.sh -PASS: check_sigtool.sh -PASS: check_unit_vg.sh -PASS: check1_clamscan.sh -PASS: check2_clamd.sh -PASS: check3_clamd.sh -PASS: check4_clamd.sh -PASS: check5_clamd_vg.sh -PASS: check6_clamd_vg.sh -SKIP: check7_clamd_hg.sh -PASS: check8_clamd_hg.sh -PASS: check9_clamscan_vg.sh - ... -============================================================================ -Testsuite summary for ClamAV 0.100.2 -============================================================================ -# TOTAL: 13 -# PASS: 12 -# SKIP: 1 -# XFAIL: 0 -# FAIL: 0 -# XPASS: 0 -# ERROR: 0 -``` - -_Notes_: - -* The `*.vg.sh` tests will be skipped unless you run `make check VG=1`. -* The `check7_clamd.hg.sh` (helgrind) is presently disabled and will be skipped. - * For details, see: [the Git commit](https://github.com/Cisco-Talos/clamav-devel/commit/2a5d51809a56be9a777ded02969a7427a3c26713) - -If you have a failure or an error in the unit tests, it could be that you are missing one or more of the prerequisites. - -If you are investigating a failure, please do the following: - -`cd unit_tests` - -Use `less` to read the log for the failed test. -Example: - -```bash -less check4_clamd.sh.log` -``` - -To submit a bug report regarding unit text failures, please follow these [bug reporting steps](../Installation-Unix.md#Reporting-a-unit-test-failure-bug). - -### Install ClamAV - -Install ClamAV with: -```bash -make install -``` - -_Tip_: If installing to the default or other system-owned directory, you may need to use `sudo`. - -### First time set-up - -_Note_: The following instructions assume you used the default install paths (i.e. `/usr/local`). If you modified the install locations using `--prefix` or `--sysconfdir` options, replace `/usr/local` with your chosen install path. - -#### `freshclam` config - -Before you can use `freshclam` to download updates, you need to create a `freshclam` config. A sample config is provided for you. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/freshclam.conf.sample /usr/local/etc/freshclam.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogRotate` - * `NotifyClamd` - * `DatabaseOwner` - -3. Create the database directory. *Tip: _You may need to use `sudo`._ - ```bash - mkdir /usr/local/share/clamav - ``` - -#### `clamd` config (optional) - -You can run `clamscan` without setting the config options for `clamd`. However, the `clamd` scanning daemon allows you to use `clamdscan` to perform faster a-la-carte scans, allows you to run multi-threaded scans, and allows you to use `clamav-milter` if you want to use ClamAV as a mail filter if you host an email server. - -Additionally, if you are a running modern versions of Linux where the FANOTIFY kernel feature is enabled, `clamd` has a feature run with On-Access Scanning*. *When properly configured*, On-Access Scanning can scan files as they are accessed and optionally block access to the file in the event that a signature alerted. - - _Note_: At this time, for On-Access Scanning to work, `clamd` must run with `sudo`/root privileges. For more details, please see our documentation on On-Access Scanning. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/clamd.conf.sample /usr/local/etc/clamd.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - * You also _need_ to select a Socket option for `clamd` so `clamdscan` and other utilities can communicate with `clamd`. You must enable _one_ of the following. - * `LocalSocket` - * `TCPSocket` - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogClean` - * `LogRotate` - * `User` - * `ScanOnAccess` - * `OnAccessIncludePath` - * `OnAccessExcludePath` - * `OnAccessPrevention` - -#### Configure SELinux for ClamAV - -Certain distributions (notably RedHat variants) when operating with SELinux enabled use the non-standard `antivirus_can_scan_system` SELinux option instead of `clamd_can_scan_system`. - -At this time, libclamav only sets the `clamd_can_scan_system` option, so you may need to manually enable `antivirus_can_scan_system`. If you don't perform this step, freshclam will log something like this when it tests the newly downloaded signature databases: - -``` -During database load : LibClamAV Warning: RWX mapping denied: Can't allocate RWX Memory: Permission denied -``` - -To allow ClamAV to operate under SELinux, run the following: -```bash -setsebool -P antivirus_can_scan_system 1 -``` - -#### Download / Update the signature database - -Before you can run a scan, you'll need to download the signature databases. Once again, you may need to run with `sudo`/root privileges. - -If you installed to a location in your system PATH: -```bash -freshclam -``` - -If you installed to another location: -```bash -/////freshclam -``` - -#### Users and on user privileges - -If you are running `freshclam` and `clamd` as root or with `sudo`, and you did not explicitely configure with `--disable-clamav`, you will want to ensure that the `DatabaseOwner` user specified in `freshclam.conf` owns the database directory so it can download signature udpates. - -The user that `clamd`, `clamdscan`, and `clamscan` run as may be the same user, but if it isn't -- it merely needs _read_ access to the database directory. - -If you choose to use the default `clamav` user to run `freshclam` and `clamd`, you'll need to create the clamav group and the clamav user account the first time you install ClamAV. - -``` -groupadd clamav -useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav -``` - -Finally, you will want to set user ownership of the database directory. -For example: -```bash -sudo chown -R clamav:clamav /usr/local/share/clamav -``` - -### Usage - -You should be all set up to run scans. - -Take a look at our [usage documentation](../Usage.md) to learn about how to use ClamAV each of the utilities. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-macOS.md clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-macOS.md --- clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix/Steps-macOS.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix/Steps-macOS.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,364 +0,0 @@ -# Installation on macOS (Mac OS X) - -Below are the steps for installing ClamAV from source on Apple macOS. - -## Install prerequisites - -The easiest way to install prerequisites on macOS is to use [Homebrew](https://brew.sh/) - -1. Install Homebrew - ```bash - /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - ``` - -2. Install ClamAV dependencies - 1. Install XCode's Command Line Tools - ```bash - xcode-select --install - ``` - 2. Install library dependencies - ```bash - brew install pcre2 openssl json-c - ``` - -3. Install the unit testing dependencies - ```bash - sudo apt-get valgrind check - ``` - - _Tip_: Valgrind may not be available in Homebrew for the latest version of macOS. - -_Note_: LLVM is also an optional dependency. LLVM will not provide any additional features, but is an alternative method for executing bytecode signatures versus using the built-in bytecode interpreter. Limited performance testing between LLVM and the bytecode interpreter did not yield conclusive evidence that one is "better" than the other. For the sake of simplicity, it is not recommended to install LLVM. - -## Download the latest stable release - -1. Open a browser and navigate to [the ClamAV downloads page](http://www.clamav.net/downloads) -2. Click `clamav-.tar.gz` link to download the latest stable release. - -## Extract the source archive - -```bash -cd ~/Downloads -tar xzf clamav-.tar.gz -cd clamav-.tar.gz -``` - -## Configure the build - -Homebrew installs libraries and applications under `/usr/local/Cellar///`. - -To configure the ClamAV build using our homebrew-installed dependencies, you may need to reference some of them explicitly. Others may be detected automatically. - -### Typical `./configure` usage - -*_Note_: Your Homebrew-installed package version directories may differ slightly. - -```bash -./configure --with-openssl=/usr/local/Cellar/openssl/1.0.2l --with-libjson=yes --enable-check -``` - -Once `./configure` completes, it will print a summary. Verify that the packages you installed are in fact being detected. - -Example configure summary output: - -```bash -configure: Summary of detected features follows - OS : darwin17.2.0 - pthreads : yes () -configure: Summary of miscellaneous features - check : -L/usr/local/lib -lcheck -R/usr/local/lib (auto) - fanotify : no (disabled) - fdpassing : 1 - IPv6 : yes -configure: Summary of optional tools - clamdtop : -lncurses (auto) - milter : yes (disabled) - clamsubmit : yes (libjson-c-dev found at /usr/local), libcurl-devel found at /usr) -configure: Summary of engine performance features - release mode: yes - llvm : no (disabled) - mempool : yes -configure: Summary of engine detection features - bzip2 : ok - zlib : /usr - unrar : yes - preclass : yes (libjson-c-dev found at /usr/local) - pcre : /usr/local/Cellar/pcre2/10.32 - libmspack : yes (Internal) - libxml2 : yes, from /usr - yara : yes - fts : yes (libc) -``` - -If you experience an error wherein `configure` output claims that `gcc` is unable to build an executable -- please see the [Troubleshooting section at the bottom](#configure----gcc-failed-to-build-executable). - -### Additional popular `./configure` options - -* `--sysconfdir` - Install the configuration files to `/etc` instead of `/usr/local/etc`: - ```bash - ./configure -–sysconfdir=/etc - ``` -* `--prefix` - Install ClamAV to a directory other than `/usr/local/`: - * Example 1: Install to a local `./install` directory. - ```bash - ./configure --prefix=`pwd`/install - ``` - * Example 2: Install ClamAV locally on an unprivileged shell account. - ```bash - ./configure --prefix=$HOME/clamav --disable-clamav - ``` -* `--disable-clamav` - _Don't_ drop super-user priveleges to run `freshclam` or `clamd` as the `clamav`* user. - ```bash - ./configure --disable-clamav - ``` - *_Tip_: Using this `--disable-clamav` means that `freshclam` and `clamd` will run with _root privleges_ if invoked using `sudo`. Running `clamd` or `clamscan` as root is **not recommended**. Instead of using this option, you can configure `freshclam` or `clamd` to drop to any other user by: - * setting the `DatabaseOwner` option in `freshclam.conf` and - * setting the `User` option in `clamd.conf`. - -Please see the `./configure --help` for additional options. - -### Compile ClamAV - -Compile ClamAV with: -```bash -make -j2 -``` - -If you experience error messages wherein the compiler is unable to find the correct openssl header or library files, you may need to reconfigure and provide explicit header and library paths. See the [Troubleshooting section below for details](#make----failed-to-find-correct-openssl-header-or-library-files). - -### Run ClamAV Unit Tests (Optional) - -For peace of mind, it can be helpful to run a small suite of unit and system tests. - -Run: -```bash -make check -``` - -All tests should pass.* Output will look something like this: - -```bash. - ... -PASS: check_clamav -PASS: check_freshclam.sh -PASS: check_sigtool.sh -PASS: check_unit_vg.sh -PASS: check1_clamscan.sh -PASS: check2_clamd.sh -PASS: check3_clamd.sh -PASS: check4_clamd.sh -PASS: check5_clamd_vg.sh -PASS: check6_clamd_vg.sh -SKIP: check7_clamd_hg.sh -PASS: check8_clamd_hg.sh -PASS: check9_clamscan_vg.sh - ... -============================================================================ -Testsuite summary for ClamAV 0.100.2 -============================================================================ -# TOTAL: 13 -# PASS: 12 -# SKIP: 1 -# XFAIL: 0 -# FAIL: 0 -# XPASS: 0 -# ERROR: 0 -``` - -_Notes_: - -* The `*.vg.sh` tests will be skipped unless you run `make check VG=1`. - * _Under macOS_, `*.vg.sh` (valgrind) tests _will fail_ due to false alerts. - * Valgrind may not be available via Homebrew for the latest version of macOS. -* The `check7_clamd.hg.sh` (helgrind) is presently disabled and will be skipped. - * For details, see: [the Git commit](https://github.com/Cisco-Talos/clamav-devel/commit/2a5d51809a56be9a777ded02969a7427a3c26713) - -If you have a failure or an error in the unit tests, it could be that you are missing one or more of the prerequisites or that there is miss-match in the header files after upgrading to a newer version of macOS. If the latter, please see the [Troubleshooting section at the bottom](#make-check----unit-tests-failed-for-seemingly-no-reason). - -If you are investigating a failure, please do the following: - -`cd unit_tests` - -Use `less` to read the log for the failed test. -Example: - -```bash -less check4_clamd.sh.log` -``` - -To submit a bug report regarding unit text failures, please follow these [bug reporting steps](../Installation-Unix.md#Reporting-a-unit-test-failure-bug). - -### Install ClamAV - -Install ClamAV with: -```bash -make install -``` - -_Tip_: If installing to the default or other system-owned directory, you may need to use `sudo`. - -### First time set-up - -_Note_: The following instructions assume you used the default install paths (i.e. `/usr/local`). If you modified the install locations using `--prefix` or `--sysconfdir` options, replace `/usr/local` with your chosen install path. - -#### `freshclam` config - -Before you can use `freshclam` to download updates, you need to create a `freshclam` config. A sample config is provided for you. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/freshclam.conf.sample /usr/local/etc/freshclam.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogRotate` - * `NotifyClamd` - * `DatabaseOwner` - -3. Create the database directory. *Tip: _You may need to use `sudo`._ - ```bash - mkdir /usr/local/share/clamav - ``` - -#### `clamd` config (optional) - -You can run `clamscan` without setting the config options for `clamd`. However, the `clamd` scanning daemon allows you to use `clamdscan` to perform faster a-la-carte scans, allows you to run multi-threaded scans, and allows you to use `clamav-milter` if you want to use ClamAV as a mail filter if you host an email server. - -1. Copy the sample config. You may need to use `sudo`: - ```bash - cp /usr/local/etc/clamd.conf.sample /usr/local/etc/clamd.conf - ``` -2. Modify the config file using your favourite text editor. Again, you may need to use `sudo`. - * At a minimum, remove the `Example` line so `freshclam` can use the config. - * You also _need_ to select a Socket option for `clamd` so `clamdscan` and other utilities can communicate with `clamd`. You must enable _one_ of the following. - * `LocalSocket` - * `TCPSocket` - - Take the time to look through the options. You can enable the sample options by deleting the `#` comment characters. - - Some popular options to enable include: - - * `LogTime` - * `LogClean` - * `LogRotate` - * `User` - -#### Download / Update the signature database - -Before you can run a scan, you'll need to download the signature databases. Once again, you may need to run with `sudo`/root privileges. - -If you installed to a location in your system PATH: -```bash -freshclam -``` - -If you installed to another location: -```bash -/////freshclam -``` - -#### Users and on user privileges - -If you are running `freshclam` and `clamd` as root or with `sudo`, and you did not explicitely configure with `--disable-clamav`, you will want to ensure that the `DatabaseOwner` user specified in `freshclam.conf` owns the database directory so it can download signature udpates. - -The user that `clamd`, `clamdscan`, and `clamscan` run as may be the same user, but if it isn't -- it merely needs _read_ access to the database directory. - -If you choose to use the default `clamav` user to run `freshclam` and `clamd`, you'll need to create the clamav group and the clamav user account the first time you install ClamAV. - -Prep by identifying an unused group id (gid), and an unused user UniqueID. - -This command will display all current group PrimaryGroupIDs: -```bash -dscl . list /Groups PrimaryGroupID | tr -s ' ' | sort -n -t ' ' -k2,2 -``` - -This command will display all current user UniqueIDs: -```bash -dscl . list /Users UniqueID | tr -s ' ' | sort -n -t ' ' -k2,2 -``` - -Then, these commands can be used to create the `clamav` group and `clamav` user. -```bash -sudo dscl . create /Groups/clamav -sudo dscl . create /Groups/clamav RealName "Clam Antivirus Group" -sudo dscl . create /Groups/clamav gid 799 # Ensure this is unique! -sudo dscl . create /Users/clamav -sudo dscl . create /Users/clamav RealName "Clam Antivirus User" -sudo dscl . create /Users/clamav UserShell /bin/false -sudo dscl . create /Users/clamav UniqueID 599 # Ensure this is unique! -sudo dscl . create /Users/clamav PrimaryGroupID 799 # Must match the above gid! -``` - -Finally, you will want to set user ownership of the database directory. -For example: -```bash -sudo chown -R clamav:clamav /usr/local/share/clamav -``` - -### Usage - -You should be all set up to run scans. - -Take a look at our [usage documentation](../Usage.md) to learn about how to use ClamAV each of the utilities. - -### Troubleshooting - -#### Configure -- `gcc` failed to build executable - -It is possible that `gcc`/`clang` is misconfigured. This is particularly likely after an upgrade to a newer versions of macOS (e.g after an upgrade from macOS High Sierra to macOS Mojave). - -Open Terminal, and run the following: - -```bash -xcode-select --install -``` - -This will download and install xcode developer tools and fix the problem. _You will be prompted (in the macOS GUI) to accept the license agreement before it will continue._ -As a follow on step, you _may_ need to reset the path to Xcode if you have several versions or want the command line tools to run without Xcode. - -```bash -xcode-select --switch /Applications/Xcode.app -xcode-select --switch /Library/Developer/CommandLineTools -``` - -> Solution shamelessly lifted from [apple stackexchange](https://apple.stackexchange.com/questions/254380/macos-mojave-invalid-active-developer-path) - -#### Make -- failed to find correct openssl header or library files - -Homebrew provides symlinks in `/usr/local/opt` to aid in the linking process: - -```bash -$ ls -l /usr/local/opt/openssl* - -lrwxr-xr-x 1 gary admin 24B Aug 21 12:39 /usr/local/opt/openssl@ -> ../Cellar/openssl/1.0.2p -lrwxr-xr-x 1 gary admin 24B Aug 21 12:39 /usr/local/opt/openssl@1.0@ -> ../Cellar/openssl/1.0.2p -lrwxr-xr-x 1 gary admin 28B Nov 20 2017 /usr/local/opt/openssl@1.1@ -> ../Cellar/openssl@1.1/1.1.0g -``` - -If they aren't automatically detected you may experience issues linking openssl. You can work around this by explicitly listing the include `-I` and library `-L` paths. - -For example: - -```bash -./configure --with-openssl=/usr/local/Cellar/openssl/1.0.2l --with-libjson=yes --enable-check CPPFLAGS="-I/usr/local/opt/openssl@1.0/include" LDFLAGS="-L/usr/local/opt/openssl@1.0/lib/" -``` - -#### Make check -- unit tests failed for seemingly no reason - -Similar to the above issue, it is possible for a mismatch in your development header files resulting in a working build that may fail the `check` test suite. - -If you're seeing one or more failed tests on a stable release of ClamAV on macOS, the following may resolve the issue: - -Open Terminal, and run the following: - -```bash -sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target / -``` - -> Solution shamelessly lifted from [the pyenv github issue tracker](https://github.com/pyenv/pyenv/issues/1219) diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix.md clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix.md --- clamav-0.101.4+dfsg/docs/UserManual/Installation-Unix.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Installation-Unix.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,261 +0,0 @@ -# Installing ClamAV on Unix / Linux / macOS from Source - -## The TL;DR Step-by-Step Instructions - -- [Debian & Ubuntu](Installation-Unix/Steps-Debian-Ubuntu.md) -- [Redhat & CentOS](Installation-Unix/Steps-REdhat-CentOS.md) -- [macOS](Installation-Unix/Steps-macOS.md) - -## Requirements - -The following is an overview of the tools, libraries, and steps needed to build ClamAV. - -Required tools: - -- `gcc` or `clang` -- GNU Make (`gmake` on UNIX systems) - -Recommended tools: - -- `check` unit testing framework - -***Required*** libraries (including development sources (i.e. `...-dev` or `...-devel`)): - -- zlib -- openssl version 0.9.8 or higher - -**Recommended** libraries (including development sources (i.e. `...-dev` or `...-devel`)): - -- pcre2 -- bzip2 -- libxml2 - -Optional libraries (including development sources (i.e. `...-dev` or `...-devel`)): - -- curl library: _required for clamsubmit_ -- json-c library: _required for clamsubmit_ -- ncurses library: _required for clamdtop_ - -ClamAV may execute Bytecode signatures using: - -- ClamAV's built-in bytecode interpreter -- LLVM for Just-In-Time (JIT) compilation* - - System-installed LLVM library (3.2-3.6) - - ClamAV's built-in version of LLVM 2.8 - - *The performance difference between using LLVM and using the interpeter is negligible. If you prefer to use LLVM / JIT for bytecode signature execution, be advised that we presently only support up to LLVM version 3.6. - -The following are thus optional, but *required* to use LLVM in place of the bytecode interpeter: - -- LLVM 3.2 - 3.6 -- A supported CPU for LLVM JIT, either of: X86, X86-64, PowerPC, PowerPC64 - -The following are optional, but needed for the LLVM JIT unit tests: - -- GNU Make (version 3.79, recommended 3.81 or newer) -- Python (version 2.5.4) - -## Installing ClamAV - -### Private installation on local shell account - -To install ClamAV locally on an unprivileged shell account you need not create any additional users or groups. Assuming your home directory is `/home/gary` you should build it as follows: - -```bash -./configure --prefix=/home/gary/clamav --disable-clamav -make; make install -``` - -The `--disable-clamav` switch disables the check for existence of the `clamav` user and group but `clamscan` would still require an unprivileged account to work in a superuser mode. - -### Global installation in system-owned directories - -#### Adding new system user and group - -If installing to the system, it is recommended to set up at least one special user account to run `freshclam` and `clamd`. You may choose to set up two separate accounts, one for each. You only need to create these accounts the first time you install ClamAV. - -These are instructions specific to some popular operating systems: - -- [Debian, Ubuntu, etc](Installation-Unix/Steps-Debian-Ubuntu.md#Users-and-on-user-privileges) -- [Redhat, CentOS, etc](Installation-Unix/Steps-Redhat-CentOS.md#Users-and-on-user-privileges) -- [macOS](Installation-Unix/Steps-macOS.md#Users-and-on-user-privileges) - -If your operating system isn't specified above, and your OS does not have the `groupadd` and `useradd` utilities, consult a system manual. **Don’t forget to lock access to the account!** - -#### Compiling ClamAV for global installation - -Once you have created the clamav user and group, please extract the archive: - -```bash -tar xzf clamav-.tar.gz -cd clamav- -``` - -Assuming you want to install the configuration files in `/etc`, configure and build the software as follows: - -```bash -./configure --sysconfdir=/etc -make -su -c "make install" -``` - -In the last step, the software is installed into the `/usr/local` directory and the config files into `/etc`. **WARNING: Never enable the SUID or SGID bits for Clam AntiVirus binaries.** - -### First-time set-up - -First, create a database directory. This would be located under the install path `share/clamav`. For example: - -- `/usr/local/share/clamav` -- `~/clamav/share/clamav` - -You will need to create `freshclam.conf` and `clamd.conf` files in the config directory. In the above example, we chose `/etc`, so run the following. - -```bash -sudo cp /etc/freshclam.conf.sample /etc/freshclam.conf -sudo cp /etc/clamd.conf.sample /etc/clamd.conf -``` - -At a minimum, you will need to edit each file and remove or comment-out the `Example` line. In addition, for `clamd.conf` you will need to enable either `LocalSocket` or `TCPSocket`. - -For additional recommendations, please read: - -- [Debian, Ubuntu, etc](Installation-Unix/Steps-Debian-Ubuntu.md#First-time-set-up) -- [Redhat, CentOS, etc](Installation-Unix/Steps-Redhat-CentOS.md#First-time-set-up) -- [macOS](Installation-Unix/Steps-macOS.md#First-time-set-up) - -### Test your installation - -To test your local installation execute: - -```bash -~/clamav/bin/freshclam -~/clamav/bin/clamscan ~ -``` - -To test your system installation execute: - -```bash -sudo freshclam -sudo clamscan ~ -``` - -## Compilation with clamav-milter enabled - -The `libmilter` package and its development files are required. To enable clamav-milter, configure ClamAV with - -```bash -./configure --enable-milter -``` - -## Using a system-installed LLVM library - -To configure ClamAV to use a system-installed LLVM library: - -```bash -./configure --with-system-llvm=/myllvm/bin/llvm-config -make -sudo make install -``` - -The argument to `--with-system-llvm` indicates the path name of the LLVM configuration utility (llvm-config). Alternatively, you may use `--enable-llvm` and `./configure` will search for LLVM in /usr/local/ and then /usr. - -Recommended versions of LLVM are 3.2 - 3.6. Some installations have reported problems using earlier LLVM versions. Versions of LLVM beyond 3.6 are not currently supported in ClamAV. - -## Running unit tests - -ClamAV includes unit tests that allow you to test that the compiled binaries work correctly on your platform. - -The first step is to use your OS’s package manager to install the `check` package. If your OS doesn’t have that package, you can download it from , build it and install it. - -To help clamav’s configure script locate `check`, it is recommended that you install `pkg-config`, preferably using your OS’s package manager, or from . - -The recommended way to run unit-tests is the following, which ensures you will get an error if unit tests cannot be built: - -```bash -./configure --enable-check -make -make check -``` - -When `make check` is finished, you should get a message similar to this: - -```bash -================== -All 8 tests passed -================== -``` - -If a unit test fails, you get a message similar to the following. Note that in older versions of make check may report failures due to the absence of optional packages. Please make sure you have the latest versions of the components noted in section /refsec:components. See the next section on how to report a bug when a unit test fails. - -```bash -======================================== -1 of 8 tests failed -Please report to https://bugzilla.clamav.net/ -======================================== -``` - -If unit tests are disabled (and you didn’t use -–enable-check), you will get this message: - -```bash -*** Unit tests disabled in this build -*** Use ./configure --enable-check to enable them - -SKIP: check_clamav -PASS: check_clamd.sh -PASS: check_freshclam.sh -PASS: check_sigtool.sh -PASS: check_clamscan.sh -====================== -All 4 tests passed -(1 tests were not run) -====================== -``` - -Running `./configure --enable-check` should tell you why. - -## Reporting a unit test failure bug - -If `make check` reports failed tests, we encourage you to report a bug on [bugzilla](https://bugzilla.clamav.net). - -When writing a bug report regarding failed unit tests, please provide the following: - -- The exact output from `make check` -- Output of `uname -mrsp` -- your `config.log` -- The following files from the `unit_tests/` directory: - - `test.log` - - `clamscan.log` - - `clamdscan.log` - -- `/tmp/clamd-test.log` if it exists -- where and how you installed the check package -- Output of `pkg-config check --cflags --libs` -- Optionally if `valgrind` is available on your platform, the output of the following: - ```bash - make check - CK_FORK=no ./libtool --mode=execute valgrind unit_tests/check_clamav - ``` - -## Obtain Latest ClamAV anti-virus signature databases - -Before you can run `clamd`, `clamdscan`, or `clamscan`, you must have ClamAV Virus Database (.cvd) file(s) installed in the appropriate location on your system. The default location for these database files are `/usr/local/share/clamav`. - -Here is a listing of currently available ClamAV Virus Database Files: - -- bytecode.cvd (signatures to detect bytecode in files) -- main.cvd (main ClamAV virus database file) -- daily.cvd (daily update file for ClamAV virus databases) -- safebrowsing.cvd (virus signatures for safe browsing) - -These files should be downloaded using the `freshclam` utility on a periodic basis. While using HTTPS to directly download the CVDs is possible, using `freshclam` is the preferred method of keeping the ClamAV virus database files up to date. `freshclam` can download database difference files (`.cdiff`) to get the latest signature definitions without downloading whole CVD files. This saves a considerable amount of bandwidth. - -For more information on how to configure `freshclam` to do automatic/scheduled updates, see the [freshclam configuration section](Configuration.md#Setting-up-auto\-updating) of our Configuration guide. - -Please see the [freshclam usage section](Usage.md#freshclam) for additional details on freshclam). - -## Binary packages - -As an alternative to building and installing from source, most Linux package managers provide pre-compiled ClamAV packages. - -For more information about installing ClamAV via a Package Manager, please visit -the ["other versions" section on the ClamAV.net Downloads page](https://www.clamav.net/download.html#otherversions). diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Installation-Windows.md clamav-0.102.1+dfsg/docs/UserManual/Installation-Windows.md --- clamav-0.101.4+dfsg/docs/UserManual/Installation-Windows.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Installation-Windows.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -# Installing ClamAV on Windows - -If you wish to build ClamAV from source using Visual Studio 2015, please head over to the [Win32 ClamAV Build Instructions](win32/README.md) located in our source release materials on [ClamAV.net](https://www.clamav.net/downloads) and on [GitHub](https://github.com/Cisco-Talos/clamav-devel). - -## Install using the ClamAV Windows Installer - -Important: Installing ClamAV using the Installer will require Administrator privileges. - -1. Download: http://www.clamav.net/downloads/production/ClamAV-0.101.4.exe -2. Locate the file in your Downloads directory. -3. Right-click on `ClamAV-0.101.4.exe` and select `Run as administrator`. You may receive a warning message along the lines of "Windows protected your PC". Select `More info` and then select `Run anyway`. -4. Select `I accept the agreement` and click `Next`. -5. Click `Next` again. If you've removed a previous installation of ClamAV, you may receive the prompt "The folder ... already exists...". If you do, select `Yes`. -6. Click `Install`. -7. Click `Finish`. -8. Press the Windows-key and type `powershell` but _DO NOT_ press `Enter`. Right-click on `Windows PowerShell` at the top of the menu and select `Run as administrator`. Your computer may warn you `Do you want to allow this app to make changes to your device?` Click `Yes`. -9. Verify that the prompt in the PowerShell window looks like this: - ```powershell - PS C:\WINDOWS\system32> - ``` - -10. In the Adminstrator PowerShell window, enter the following to navigate to the ClamAV install directory: - ```powershell - cd "c:\program files\clamav" - ``` - -Continue on to "First Time Set-Up" below... - -## Install using the ClamAV Portable Install Package - -1. Download: https://www.clamav.net/downloads/production/clamav-0.101.4-win-x64-portable.zip -2. Unzip it. -3. Open the `clamav-0.101.4-win-x64-portable` directory. -4. Hold down Shift and then right-click on the background in the current directory (but not on one of the files). Select `"Open PowerShell window here"`. If that option doesn't appear, try again. - -Continue on to "First Time Set-Up"... - -## First Time Set-Up - -In the PowerShell window, perform the following tasks: - -* Run: - ```powershell - copy .\conf_examples\freshclam.conf.sample .\freshclam.conf - ``` -* Run: - ```powershell - write.exe .\freshclam.conf - ``` -* WordPad will pop up. Delete the line that says "Example". Save the file and close WordPad. - -## Next Steps - -### Download the Signature Databases - -Before you can start the ClamAV scanning engine (using either `clamd` or `clamscan`), you must _first_ have ClamAV Virus Database (.cvd) file(s) installed in the appropriate location on your system. The default location for these database files is C:\Program Files\ClamAV\database, the database directory of your ` (in Windows). - -Continuing in the PowerShell window: - -1. Run: - ```powershell - .\freshclam.exe - ``` -2. freshclam will download some files and drop them in the database directory. This can take a minute or two depending on how fast your internet connection is. The files are a pretty large. -3. You are now ready to perform scans with ClamAV. If you using the portable install package, you may now copy the entire `clamav-0.100.1-win-x64-portable` directory to the computer(s) you wish to scan. - -### Steps to Perform Basic Scanning - -* Run this to scan the files in the current directory: - ```powershell - .\clamscan.exe . - ``` - - This will scan the current directory. At the end of the scan, it will display a summary. If you notice in the clamscan output, it only scanned something like 60 files, even though there are more files in subdirectories. By default, clamscan will only scan files in the current directory. - -* Run this to scan all the files in the current directory: - ```powershell - .\clamscan.exe --recursive . - ``` - -* Run this to scan ALL the files on your C: drive, it will take **quite** a while. Keep in mind that you can cancel it at any time by pressing `Ctrl-C`: - ```powershell - .\clamscan --recursive C:\ - ``` - -* For more information on ways you can use clamscan, run: - ```powershell - .\clamscan.exe --help - ``` - -### Faster a-la-carte Scanning with `clamd` - -You may have noticed that `clamscan` takes a while to get started. This is because it loads the signature database each time you start a scan. If you require faster scanning of individual files, you will want to use `clamd` with `clamdscan` instead. - -Continuing in the PowerShell window: - -1. Run: - ```powershell - .\clamd.exe - ``` - The application will take a moment to load and then appear to hang, but it is in fact waiting for scanning commands from `clamdscan`. -2. Open a second PowerShell window as you did above, in the same directory. -3. In the second PowerShell window, you can now run `clamdscan` much the same way you did with `clamscan` above. - ```powershell - .\clamdscan.exe . - ``` diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Introduction.md clamav-0.102.1+dfsg/docs/UserManual/Introduction.md --- clamav-0.101.4+dfsg/docs/UserManual/Introduction.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Introduction.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,145 +0,0 @@ -# Introduction - -Clam AntiVirus is an open source (GPLv2) anti-virus toolkit, designed especially for e-mail scanning on mail gateways. It provides a number of utilities including a flexible and scalable multi-threaded daemon, a command line scanner and advanced tool for automatic database updates. The core of the package is an anti-virus engine available in a form of shared library. - -## Features - -### Capabilities - -- ClamAV is designed to scan files quickly. -- Real time protection (Linux only). Our scanning daemon supports on-access scanning on modern versions of Linux, including the ability to block file access until a file has been scanned. -- ClamAV detects over 1 million viruses, worms and trojans, including Microsoft Office macro viruses, mobile malware, and other threats. -- The built-in bytecode interpreter allows the ClamAV signature writers to create and distribute very complex detection routines and remotely enhance the scanner’s functionality. -- Signed signature databases ensure that ClamAV will only execute trusted signature definitions. -- ClamAV scans within archives and compressed files but also protects against archive bombs. Built-in archive extraction capabilities include: - - Zip (including SFX) - - RAR (including SFX) - - 7Zip - - ARJ (including SFX) - - Tar - - CPIO - - Gzip - - Bzip2 - - DMG - - IMG - - ISO 9660 - - PKG - - HFS+ partition - - HFSX partition - - APM disk image - - GPT disk image - - MBR disk image - - XAR - - XZ - - MS OLE2 - - MS Cabinet Files (including SFX) - - MS CHM (Compiled HTML) - - MS SZDD compression format - - BinHex - - SIS (SymbianOS packages) - - AutoIt - - InstallShield -- Supports Windows executable file parsing, also known as Portable Executables (PE) both 32/64-bit, including PE files that are compressed or obfuscated with: - - AsPack - - UPX - - FSG - - Petite - - PeSpin - - NsPack - - wwpack32 - - MEW - - Upack - - Y0da Cryptor -- Supports ELF and Mach-O files (both 32- and 64-bit) -- Supports almost all mail file formats -- Support for other special files/formats includes: - - HTML - - RTF - - PDF - - Files encrypted with CryptFF and ScrEnc - - uuencode - - TNEF (winmail.dat) -- Advanced database updater with support for scripted updates, digital signatures and DNS based database version queries - -### License - -ClamAV is licensed under the GNU General Public License, Version 2. - -### Supported platforms - -Clam AntiVirus is highly cross-platform. The development team cannot test every OS, so we have chosen to test ClamAV using the two most recent Long Term Support (LTS) versions of each of the most popular desktop operating systems. Our regularly tested operating systems include: - -- GNU/Linux - - Ubuntu - - 16.04 - - 18.04 - - Debian - - 7 - - 8 - - CentOS - - 6 - - 7 -- UNIX - - Solaris - - 11 - - FreeBSD - - 10 - - 11 - - macOS - - 10.13 (High Sierra) - - 10.14 (Mojave) -- Windows - - 7 - - 10 - -## Recommended System Requirements - -The following minimum recommended system requirements are for using `clamscan` or `clamd` and `clamdscan` binaries with the standard ClamAV signature database provided by Cisco. - -Minimum recommended RAM: - -- FreeBSD and Linux server edition: 1 GiB+ -- Linux non-server edition: 2 GiB+ -- Windows 7 & 10 32-bit: 2 GiB+ -- Windows 7 & 10 64-bit: 3 GiB+ -- macOS: 3 GiB+ - -Minimum recommended CPU: - -- FreeBSD and Linux systems: 1 CPU 2.0 Ghz+ -- Windows 7 & 10: 1 CPU 2.0 Ghz+ -- OSX: 2 CPUs at 2.0 Ghz+ - -Minimum available hard disk space required: - -For the ClamAV application we recommend having 5 GB of free space available. This recommendation is in addition to the recommended disk space for each OS. - -_Please note_: The tests to determine these minimum requirements were performed on systems that were not running other applications. If other applications are being run on the system, additional resources will be required in addition to our recommended minimums. - -## Mailing lists and IRC channel - -If you have a trouble installing or using ClamAV try asking on our mailing lists. There are four lists available: - -- **clamav-announce\*lists.clamav.net** - info about new versions, moderated -- **clamav-users\*lists.clamav.net** - user questions -- **clamav-devel\*lists.clamav.net** - technical discussions -- **clamav-virusdb\*lists.clamav.net** - database update announcements, moderated - -You can subscribe and search the mailing list archives at: - -Alternatively you can try asking on the `#clamav` IRC channel - launch your favourite irc client and type: - -```bash - /server irc.freenode.net - /join #clamav -``` - -## Submitting New or Otherwise Undetected Malware - -If you've got a virus which is not detected by the current version of ClamAV using the latest signature databases, please submit the sample for review at our website: - - - -Likewise, if you have a benign file that is flagging as a virus and you wish to report a False Positive, please submit the sample for review at our website: - - diff -Nru clamav-0.101.4+dfsg/docs/UserManual/OnAccess.md clamav-0.102.1+dfsg/docs/UserManual/OnAccess.md --- clamav-0.101.4+dfsg/docs/UserManual/OnAccess.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/OnAccess.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,115 +0,0 @@ -# On-Access Scanning - ---- - -## Purpose - ---- - -This guide is for users interested in leveraging and understanding ClamAV's On-Access Scanning feature. It will walk through how to set up and use the On-Access Scanner and step through some common issues and their solutions. - ---- - -## Requirements - ---- - -On-Access is only available on Linux systems. On Linux, On-Access requires a `kernel version >= 3.8`. This is because it leverages a kernel api called [fanotify](http://man7.org/linux/man-pages/man7/fanotify.7.html) to perform its blocking. - ---- - -## General Use - ---- - -To use ClamAV's On-Access Scanner, simply open `clamd.conf`, set the `ScanOnAccess` option to `yes`, and then specify the path(s) you would like to recursively watch with the `OnAccessIncludePath` option. Finally, set `OnAccessPrevention` to `yes`. Then, run `clamd` with elevated permissions (e.g. `sudo clamd`). If all went well, the On-Access scanner will now be actively protecting the specified path(s). You can test this by dropping an eicar file into the specified path, and attempting to read/access it (e.g. `cat eicar.txt`). This will result in an "Operation not permitted" message, triggered by fanotify blocking the access attempt at the kernel level. - ---- - -## Troubleshooting ---- - -Some OS distributors have disabled fanotify, despite kernel support. You can check for fanotify support on your kernel by running the command: - -> $ cat /boot/config- | grep FANOTIFY - -You should see the following: - -``` -CONFIG_FANOTIFY=y -CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y -``` - -If you see: - -``` -# CONFIG_FANOTIFY_ACCESS_PERMISSIONS is not set -``` - -Then ClamAV's On-Access Scanner will still function, scanning and alerting on files normally in real time. However, it will be unable to block access attempts on malicious files. We call this `notify-only` mode. - ---- - -ClamAV's On-Access Scanning system uses a scheme called Dynamic Directory Determination (DDD for short) which is a shorthand way of saying that it tracks the layout of every directory specified with `OnAccessIncludePath` dynamically, and recursively, in real time. It does this by leveraging [inotify](http://man7.org/linux/man-pages/man7/inotify.7.html) which by default has a limited number of watchpoints available for use by a process at any given time. Given the complexity of some directory hierarchies, ClamAV may warn you that it has exhausted its supply of inotify watchpoints (8192 by default). To increase the number of inotify watchpoints available for use by ClamAV (to 524288), run the following command: - -> $ echo 524288 | sudo tee -a /proc/sys/fs/inotify/max_user_watches - ---- - -The `OnAccessIncludePath` option will not accept `/` as a valid path. This is because fanotify works by blocking a process' access to a file until a access_ok or access_denied determination has been made by the original fanotify calling process. Thus, by placing fanotify watchpoints on the entire filesystem, key system files may have their access blocked at the kernel level, which will result in a system lockup. - -This restriction was made to prevent users from "shooting themselves in the foot." However, clever users will find it's possible to circumvent this restriction by using multiple `OnAccessIncludePath` options to protect most all the filesystem anyways, or simply the paths they truly care about. - ---- - -The `OnAccessMountPath` option uses a different fanotify api configuration which makes it incompatible with `OnAccessIncludePath` and the DDD System. Therefore, inotify will not be a concern when using this option. Unfortunately, this also means `OnAccessExtraScanning` (which is built around catching inotify events), and `OnAccessExcludePath` (which is built upon the DDD System) cannot be used in conjunction with `OnAccessMountPath`. - ---- - -## Configuration and Recipes - ---- - -More nuanced behavior can be coerced from ClamAV's On-Access Scanner via careful modification to `clamd.conf`. Each option related to On-Access Scanning is easily identified by looking for the `OnAccess` prefix pre-pended to each option. The default `clamd.conf` file contains descriptions of each option, along with any documented limitations or safety features. - -Below are examples of common use cases, recipes for the correct minimal configuration, and the expected behavioral result. - ---- - -#### Use Case 0x0 - - User needs to watch the entire file system, but blocking malicious access attempts isn't a concern - ``` - ScanOnAccess yes - OnAccessMountPath / - OnAccessExcludeRootUID yes - ``` - - This configuration will put the On-Access Scanner into `notify-only` mode. It will also ensure only non-root, non-clam, user processes will trigger scans against the filesystem. - ---- - -#### Use Case 0x1 - - System Administrator needs to watch the home directory of multiple Users, but not all users. Blocking access attempts is un-needed. - ``` - ScanOnAccess yes - OnAccessIncludePath /home - OnAccessExcludePath /home/user2 - OnAccessExcludePath /home/user4 - ``` - - With this configuration, the On-Access Scanner will watch the entirety of the `/home` directory recursively in `notify-only` mode. However, it will recursively exclude the `/home/user2` and `/home/user4` directories. - ---- - -#### Use Case 0x2 - - The user needs to protect a single directory non-recursively and ensure all access attempts on malicious files are blocked. - ``` - ScanOnAccess yes - OnAccessIncludePath /home/user/Downloads - OnAccessPrevention yes - OnAccessDisableDDD yes - ``` - - The configuration above will result in non-recursive real-time protection of the `/home/user/Downloads` directory by ClamAV's On-Access Scanner. Any access attempts that ClamAV detects on malicious files within the top level of the directory hierarchy will be blocked by fanotify at the kernel level. - ---- diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/AuthenticodeRules.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/AuthenticodeRules.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/AuthenticodeRules.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/AuthenticodeRules.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -# Trusted and Revoked Certificates - -Clamav 0.98 checks signed PE files for certificates and verifies each certificate in the chain against a database of trusted and revoked certificates. The signature format is - -``` - Name;Trusted;Subject;Serial;Pubkey;Exponent;CodeSign;TimeSign;CertSign; - NotBefore;Comment[;minFL[;maxFL]] -``` - -where the corresponding fields are: - -- `Name:` name of the entry - -- `Trusted:` bit field, specifying whether the cert is trusted. 1 for trusted. 0 for revoked - -- `Subject:` sha1 of the Subject field in hex - -- `Serial:` the serial number as clamscan –debug –verbose reports - -- `Pubkey:` the public key in hex - -- `Exponent:` the exponent in hex. Currently ignored and hardcoded to 010001 (in hex) - -- `CodeSign:` bit field, specifying whether this cert can sign code. 1 for true, 0 for false - -- `TimeSign:` bit field. 1 for true, 0 for false - -- `CertSign:` bit field, specifying whether this cert can sign other certs. 1 for true, 0 for false - -- `NotBefore:` integer, cert should not be added before this variable. Defaults to 0 if left empty - -- `Comment:` comments for this entry - -The signatures for certs are stored inside `.crb` files. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/BodySignatureFormat.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/BodySignatureFormat.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/BodySignatureFormat.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/BodySignatureFormat.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,90 +0,0 @@ -# Body-based Signature Content Format - -ClamAV stores all body-based signatures in a hexadecimal format. In this section by a hex-signature we mean a fragment of malware’s body converted into a hexadecimal string which can be additionally extended using various wildcards. - -## Hexadecimal format - -You can use `sigtool --hex-dump` to convert any data into a hex-string: - -```bash -zolw@localhost:/tmp/test$ sigtool --hex-dump -How do I look in hex? -486f7720646f2049206c6f6f6b20696e206865783f0a -``` - -## Wildcards - -ClamAV supports the following wildcards for hex-signatures: - -- `??` - - Match any byte. - -- `a?` - - Match a high nibble (the four high bits). - -- `?a` - - Match a low nibble (the four low bits). - -- `*` - - Match any number of bytes. - -- `{n}` - - Match `n` bytes. - -- `{-n}` - - Match `n` or less bytes. - -- `{n-}` - - Match `n` or more bytes. - -- `{n-m}` - - Match between `n` and `m` bytes (where `m > n`). - -- `HEXSIG[x-y]aa` or `aa[x-y]HEXSIG` - - Match `aa` anchored to a hex-signature, see [Bugzilla ticket 776](https://bugzilla.clamav.net/show_bug.cgi?id=776) for discussion and - examples. - -The range signatures `*` and `{}` virtually separate a hex-signature into two parts, eg. `aabbcc*bbaacc` is treated as two sub-signatures `aabbcc` and `bbaacc` with any number of bytes between them. It’s a requirement that each sub-signature includes a block of two static characters somewhere in its body. Note that there is one exception to this restriction; that is when the range wildcard is of the form `{n}` with `n<128`. In this case, ClamAV uses an optimization and translates `{n}` to the string consisting of `n ??` character wildcards. Character wildcards do not divide hex signatures into two parts and so the two static character requirement does not apply. - -## Character classes - -ClamAV supports the following character classes for hex-signatures: - -- `(B)` - - Match word boundary (including file boundaries). - -- `(L)` - - Match CR, CRLF or file boundaries. - -- `(W)` - - Match a non-alphanumeric character. - -## Alternate strings - -- Single-byte alternates (clamav-0.96) `(aa|bb|cc|...)` or `!(aa|bb|cc|...)` Match a member from a set of bytes (eg: `aa`, `bb`, `cc`, ...). - - Negation operation can be applied to match any non-member, assumed to be one-byte in length. - - Signature modifiers and wildcards cannot be applied. - -- Multi-byte fixed length alternates `(aaaa|bbbb|cccc|...)` or `!(aaaa|bbbb|cccc|...)` Match a member from a set of multi-byte alternates (eg: aaaa, bbbb, cccc, ...) of n-length. - - All set members must be the same length. - - Negation operation can be applied to match any non-member, assumed to be n-bytes in length (clamav-0.98.2). - - Signature modifiers and wildcards cannot be applied. - -- Generic alternates (clamav-0.99) `(alt1|alt2|alt3|...)` Match a member from a set of alternates (eg: alt1, alt2, alt3, ...) that can be of variable lengths. - - Negation operation cannot be applied. - - Signature modifiers and nibble wildcards (eg: `??, a?, ?a`) can be applied. - - Ranged wildcards (eg: `{n-m}`) are limited to a fixed range of less than 128 bytes (eg: `{1} -> {127}`). - -Note that using signature modifiers and wildcards classifies the alternate type to be a generic alternate. Thus single-byte alternates and multi-byte fixed length alternates can use signature modifiers and wildcards but will be classified as generic alternate. This means that negation cannot be applied in this situation and there is a slight performance impact. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/BytecodeSignatures.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/BytecodeSignatures.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/BytecodeSignatures.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/BytecodeSignatures.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -# Bytecode Signatures - -Bytecode Signatures are the means by which more complex matching can be performed by writing C code to parse sample content at various stages in file extraction. - -It is less complicated than it sounds. Essentially the signature author writes a function in C is compiled down to an intermediate language called "bytecode". This bytecode is encoded in ASCII `.cbc` file and distributed in `bytecode.[cvd|cld]`. When the database is loaded, ClamAV can interpret this bytecode to execute the function. - -Bytecode functions are provided with a set of API's that may be used to access the sample data, and to access what metadata ClamAV already has concerning the sample. - -The function may at any time call an API to flag the sample as malicious, and may provide the signature/virus name at that time. This means a single bytecode signature (function) is written to handle a given file type and may trigger different alerts with different signature names as additional malicious characteristics for the file type are identified. That isn't to say that only one bytecode signature may be assigned to a given filetype, but that a single author may find it to be more efficient to use a bytecode signature to identify more than one type of malware. - -The specifics on how to write and compile bytecode signatures are outside of the scope of this documentation. Extensive documentation on ClamAV Bytecode Signatures are provided with the [ClamAV Bytecode Compiler](https://github.com/vrtadmin/clamav-bytecode-compiler). diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/ContainerMetadata.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/ContainerMetadata.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/ContainerMetadata.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/ContainerMetadata.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -# Signatures based on container metadata - -ClamAV 0.96 allows creating generic signatures matching files stored inside different container types which meet specific conditions. The signature format is: - -``` - VirusName:ContainerType:ContainerSize:FileNameREGEX: - FileSizeInContainer:FileSizeReal:IsEncrypted:FilePos: - Res1:Res2[:MinFL[:MaxFL]] -``` - -where the corresponding fields are: - -- `VirusName:` Virus name to be displayed when signature matches. - -- `ContainerType:` The file type containing the target file. For example: - - `CL_TYPE_ZIP`, - - `CL_TYPE_RAR`, - - `CL_TYPE_ARJ`, - - `CL_TYPE_MSCAB`, - - `CL_TYPE_7Z`, - - `CL_TYPE_MAIL`, - - `CL_TYPE_(POSIX|OLD)_TAR`, - - `CL_TYPE_CPIO_(OLD|ODC|NEWC|CRC)` - - Use `*` as a wild card to indicate that container type may be any file type. - For a full list of ClamAV file types, see the [ClamAV File Types Reference](ClamAVFileTypes.md). - -- `ContainerSize:` size of the container file itself (eg. size of the zip archive) specified in bytes as absolute value or range `x-y`. - -- `FileNameREGEX:` regular expression describing name of the target file - -- `FileSizeInContainer:` usually compressed size; for MAIL, TAR and CPIO == `FileSizeReal`; specified in bytes as absolute value or range. - -- `FileSizeReal:` usually uncompressed size; for MAIL, TAR and CPIO == `FileSizeInContainer`; absolute value or range. - -- `IsEncrypted:` 1 if the target file is encrypted, 0 if it’s not and `*` to ignore - -- `FilePos:` file position in container (counting from 1); absolute value or range. - -- `Res1:` when `ContainerType` is `CL_TYPE_ZIP` or `CL_TYPE_RAR` this field is treated as a CRC sum of the target file specified in hexadecimal format; for other container types it’s ignored. - -- `Res2:` not used as of ClamAV 0.96. - -The signatures for container files are stored inside `.cdb` files. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/DatabaseInfo.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/DatabaseInfo.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/DatabaseInfo.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/DatabaseInfo.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -# Database Info - -The `.info` file format specifies information about the other database files unpacked from a CVD or CLD database archive. This file exists for the purposes of validating the correctness of the official ClamAV database container files and cannot be loaded a la carte. - -The format is simply: - -``` -name:size:sha256 -``` - -`name`: The database file name. - -`size`: The size in bytes of the database. - -`sha256`: A SHA256 hash of the database. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/DynamicConfig.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/DynamicConfig.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/DynamicConfig.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/DynamicConfig.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -# Dynamic Configuration (DCONF) - -ClamAV supports a limited set of configuration options that may be enabled or disabled via settings in the `*.cfg` database. At this time, these settings are distributed in `daily.cfg`. - -The goal of DCONF is to enable the ClamAV team to rapidly disable new or experimental features for specific ClamAV versions if a significant defect is discovered after release. - -This database is small, and the settings are largely vestigial. The team has not had a need to disable many features in a long time, and so the ClamAV versions in the settings at this time should no longer be in use. - -The strings and values referenced in `daily.cfg` are best cross-referenced with the macros and structures defined here: - -* https://github.com/Cisco-Talos/clamav-devel/blob/dev/0.101/libclamav/dconf.h#L49 -* https://github.com/Cisco-Talos/clamav-devel/blob/dev/0.101/libclamav/dconf.c#L54 - -The format for a DCONF signature is: - -``` -Category:Flags:StartFlevel:EndFlevel -``` - -`Category` may be one of: - -* PE -* ELF -* MACHO -* ARCHIVE -* DOCUMENT -* MAIL -* OTHER -* PHISHING -* BYTECODE -* STATS -* PCRE - -`Flags`: - -Every feature that may be configured via DCONF is listed in `struct dconf_module modules` in `libclamav/dconf.c`. Any given feature may be default-on or default-off. Default-on features have the 4th field set to a `1` and default off are set to `0`. The `Flags` field for a given `Category` overrides the defaults for all of the options listed under that category. - -A settings of `0x0`, for example, means that all options the category be disabled. - -The macros listed in `libclamav/dconf.h` will help you identify which bits to set to get the desired results. - -`StartFlevel`: - -This is the [FLEVEL](FunctionalityLevels.md) of the minimum ClamAV engine for which you want the settings to be in effect. - -`EndFlevel`: - -This is the [FLEVEL](FunctionalityLevels.md) of the maximum ClamAV engine for which you want the settings to be in effect. You may wish to select `255` to override the defaults of future releases. - -## Example - -Consider the `OTHER_CONF_PDFNAMEOBJ` option in the `category` `OTHER`. - -```c -#define OTHER_CONF_UUENC 0x1 // Default: 1 -#define OTHER_CONF_SCRENC 0x2 // Default: 1 -#define OTHER_CONF_RIFF 0x4 // Default: 1 -#define OTHER_CONF_JPEG 0x8 // Default: 1 -#define OTHER_CONF_CRYPTFF 0x10 // Default: 1 -#define OTHER_CONF_DLP 0x20 // Default: 1 -#define OTHER_CONF_MYDOOMLOG 0x40 // Default: 1 -#define OTHER_CONF_PREFILTERING 0x80 // Default: 1 -#define OTHER_CONF_PDFNAMEOBJ 0x100 // Default: 1 -#define OTHER_CONF_PRTNINTXN 0x200 // Default: 1 -#define OTHER_CONF_LZW 0x400 // Default: 1 -``` - -All of the `OTHER` options, including `OTHER_CONF_PDFNAMEOBJ` are default-on. To disable the option for ClamAV v0.100.X but leave the other options in their default settings, we would need to set the flags to: - -```binary -0110 1111 1111 - ^pdfnameobj off -``` - -Or in hex: `0x6FF` - -The example setting to place in `daily.cfg` then woudl be: - -``` -OTHER:0x6FF:90:99 -``` diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/EncryptedArchives.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/EncryptedArchives.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/EncryptedArchives.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/EncryptedArchives.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -# Passwords for archive files \[experimental\] - -ClamAV 0.99 allows for users to specify password attempts for certain password-compatible archives. Passwords will be attempted in order of appearance in the password signature file which use the extension of `.pwdb`. If no passwords apply or none are provided, ClamAV will default to the original behavior of parsing the file. Currently, as of ClamAV 0.99 \[flevel 81\], only `.zip` archives using the traditional PKWARE encryption are supported. The signature format is - -``` -SignatureName;TargetDescriptionBlock;PWStorageType;Password -``` - -where: - -- `SignatureName`: name to be displayed during debug when a password is successful - -- `TargetDescriptionBlock`: provides information about the engine and target file with comma separated Arg:Val pairs - - `Engine:X-Y`: Required engine functionality level. See the [FLEVEL reference](FunctionalityLevels.md) for details. - - `Container:CL_TYPE_*`: File type of applicable containers - -- `PWStorageType`: determines how the password field is parsed - - 0 = cleartext - - 1 = hex - -- `Password`: value used in password attempt - -The signatures for password attempts are stored inside `.pwdb` files. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/ExtendedSignatures.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/ExtendedSignatures.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/ExtendedSignatures.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/ExtendedSignatures.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,37 +0,0 @@ -# Extended signature format - -The extended signature format is ClamAV's most basic type of body-based signature since the deprecation of the original `.db` database format. - -Extended sigantures allow for specification of additional information beyond just hexidecimal content such as a file "target type", virus offset, or engine functionality level (FLEVEL), making the detection more reliable. - -The format is: - -``` - MalwareName:TargetType:Offset:HexSignature[:min_flevel:[max_flevel]] -``` - -`MalwareName`: The virus name. Should conform to the standards defined [here](../Signatures.md#Signature-names). - -`TargetType`: A number specifying the type of the target file: [Target Types](FileTypes.md#Target-Types) - -`Offset`: An asterisk or a decimal number `n` possibly combined with a special modifier: - -- `*` = any -- `n` = absolute offset -- `EOF-n` = end of file minus `n` bytes - -Signatures for PE, ELF and Mach-O files additionally support: - -- `EP+n` = entry point plus n bytes (`EP+0` for `EP`) -- `EP-n` = entry point minus n bytes -- `Sx+n` = start of section `x`’s (counted from 0) data plus `n` bytes -- `SEx` = entire section `x` (offset must lie within section boundaries) -- `SL+n` = start of last section plus `n` bytes - -All the above offsets except `*` can be turned into **floating offsets** and represented as `Offset,MaxShift` where `MaxShift` is an unsigned integer. A floating offset will match every offset between `Offset` and `Offset+MaxShift`, eg. `10,5` will match all offsets from 10 to 15 and `EP+n,y` will match all offsets from `EP+n` to `EP+n+y`. Versions of ClamAV older than 0.91 will silently ignore the `MaxShift` extension and only use `Offset`. Optional `MinFL` and `MaxFL` parameters can restrict the signature to specific engine releases. All signatures in the extended format must be placed inside `*.ndb` files. - -`HexSignature`: The body-based content matching [format](BodySignatureFormat.md). - -`min_flevel`: (optional) The minimum ClamAV engine that the file type signature works with. See the [FLEVEL reference](FunctionalityLevels.md) for details. To be used in the event that file type support has been recently added. - -`max_flevel`: (optional, requires `min_flevel`) The maximum ClamAV engine that the file type signature works with. To be used in the event that file type support has been recently removed. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/FileTypeMagic.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypeMagic.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/FileTypeMagic.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypeMagic.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -# File Type Magic - -ClamAV's primary mechanism for determining file types is to match the file with a File Type Magic signature. These file type signatures are compiled into ClamAV, and may also be overridden dynamically using the definition founds found in a `*.ftm` file. - -The ClamAV standard signature database includes these definitions in `daily.ftm`. - -The signature format is not too disimilar from NDB body-based signatures. - -The format is: - -``` - magictype:offset:magicbytes:name:type:type[:min_flevel[:max_flevel]] -``` - -Where: - -`magictype`: Supported magic types include: - -* 0 - direct memory comparison of `magicbytes` for file types -* 1 - The `magicbytes` use the body-based content matching [format](BodySignatureFormat.md). -* 4 - direct memory comparison of `magicbytes` for partition types (HFS+, HFSX) - -`offset`: The offset from start of the file to match against. May be `*` if `magictype` is 1. - -`name`: A descriptive name for the file type. - -`rtype`: Usually CL_TYPE_ANY. - -`type`: The CL_TYPE corresponding with the file type signature. See the [CL_TYPE reference](ClamAVFileTypes.md) for details. - -`min_flevel`: (optional) The minimum ClamAV engine that the file type signature works with. See the [FLEVEL reference](FunctionalityLevels.md) for details. To be used in the event that file type support has been recently added. - -`max_flevel`: (optional, requires `min_flevel`) The maximum ClamAV engine that the file type signature works with. To be used in the event that file type support has been recently removed. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/FileTypes.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypes.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/FileTypes.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/FileTypes.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,120 +0,0 @@ -# ClamAV File Types - -ClamAV maintains it's own file typing format and assigns these types using either: - -- Evaluation of a unique sequence of bytes at the start of a file ([File Type Magic](Signatures/FileTypeMagic.md)). -- File type indicators when parsing container files. - - For example: - CL_TYPE_SCRIPT may be assigned to data contained in a PDF when the PDF indicates that a stream of bytes is "Javascript" -- File type determination based on the names or characteristics contained within the file. - - For example: - CL_TYPE_OOXML_WORD may be assigned to a Zip file containing files with specific names. - -## Target Types - -A Target Type is an integer that indicates which kind of file the signature will match against. Target Type notation was first created for the purposes writing efficient signatures. A signature with a target type of `0` will be run against every file type, and thus is not ideal. However, the Target Type notation is limited and it may be unavoidable. - -Although the newer CL_TYPE string name notation has replaced the Target Type for some signature formats, many signature formats require a target type number. - -This is the current list of available Targe Types: - -- 0 = any file -- 1 = Portable Executable, both 32- and 64-bit. -- 2 = OLE2 containers, including their specific macros. The OLE2 format is primarily used by MS Office and MSI installation files. -- 3 = HTML (normalized) -- 4 = Mail file -- 5 = Graphics -- 6 = ELF -- 7 = ASCII text file (normalized) -- 8 = Unused -- 9 = Mach-O files -- 10 = PDF files -- 11 = Flash files -- 12 = Java class files - -**_Important_: HTML, ASCII, Javascript are all normalized. - -- ASCII: - - All lowercase. -- HTML: - - Whitespace transformed to spaces, tags/tag attributes normalized, all lowercase. -- Javascript: - - All strings are normalized (hex encoding is decoded), numbers are parsed and normalized, local variables/function names are normalized to ’n001’ format, argument to eval() is parsed as JS again, unescape() is handled, some simple JS packers are handled, output is whitespace normalized. - -## CL_TYPEs - -ClamAV Types are prefixed with `CL_TYPE_`. The following is an exhaustive list of all current CL_TYPE's. - -| CL_TYPE | Description | -|------------------------|--------------------------------------------------------------| -| `CL_TYPE_7Z` | 7-Zip Archive | -| `CL_TYPE_7ZSFX` | Self-Extracting 7-Zip Archive | -| `CL_TYPE_APM` | Disk Image - Apple Partition Map | -| `CL_TYPE_ARJ` | ARJ Archive | -| `CL_TYPE_ARJSFX` | Self-Extracting ARJ Archive | -| `CL_TYPE_AUTOIT` | AutoIt Automation Executable | -| `CL_TYPE_BINARY_DATA` | binary data | -| `CL_TYPE_BINHEX` | BinHex Macintosh 7-bit ASCII email attachment encoding | -| `CL_TYPE_BZ` | BZip Compressed File | -| `CL_TYPE_CABSFX` | Self-Extracting Microsoft CAB Archive | -| `CL_TYPE_CPIO_CRC` | CPIO Archive (CRC) | -| `CL_TYPE_CPIO_NEWC` | CPIO Archive (NEWC) | -| `CL_TYPE_CPIO_ODC` | CPIO Archive (ODC) | -| `CL_TYPE_CPIO_OLD` | CPIO Archive (OLD, Little Endian or Big Endian) | -| `CL_TYPE_CRYPTFF` | Files encrypted by CryptFF malware | -| `CL_TYPE_DMG` | Apple DMG Archive | -| `CL_TYPE_ELF` | ELF Executable (Linux/Unix program or library) | -| `CL_TYPE_GPT` | Disk Image - GUID Partition Table | -| `CL_TYPE_GRAPHICS` | TIFF (Little Endian or Big Endian) | -| `CL_TYPE_GZ` | GZip Compressed File | -| `CL_TYPE_HTML_UTF16` | Wide-Character / UTF16 encoded HTML | -| `CL_TYPE_HTML` | HTML data | -| `CL_TYPE_HWP3` | Hangul Word Processor (3.X) | -| `CL_TYPE_HWPOLE2` | Hangul Word Processor embedded OLE2 | -| `CL_TYPE_INTERNAL` | Internal properties | -| `CL_TYPE_ISHIELD_MSI` | Windows Install Shield MSI installer | -| `CL_TYPE_ISO9660` | ISO 9660 file system for optical disc media | -| `CL_TYPE_JAVA` | Java Class File | -| `CL_TYPE_LNK` | Microsoft Windows Shortcut File | -| `CL_TYPE_MACHO_UNIBIN` | Universal Binary/Java Bytecode | -| `CL_TYPE_MACHO` | Apple/NeXTSTEP Mach-O Executable file format | -| `CL_TYPE_MAIL` | Email file | -| `CL_TYPE_MBR` | Disk Image - Master Boot Record | -| `CL_TYPE_MHTML` | MHTML Saved Web Page | -| `CL_TYPE_MSCAB` | Microsoft CAB Archive | -| `CL_TYPE_MSCHM` | Microsoft CHM help archive | -| `CL_TYPE_MSEXE` | Microsoft EXE / DLL Executable file | -| `CL_TYPE_MSOLE2` | Microsoft OLE2 Container file | -| `CL_TYPE_MSSZDD` | Microsoft Compressed EXE | -| `CL_TYPE_NULSFT` | NullSoft Scripted Installer program | -| `CL_TYPE_OLD_TAR` | TAR archive (old) | -| `CL_TYPE_OOXML_HWP` | Hangul Office Open Word Processor (5.X) | -| `CL_TYPE_OOXML_PPT` | Microsoft Office Open XML PowerPoint | -| `CL_TYPE_OOXML_WORD` | Microsoft Office Open Word 2007+ | -| `CL_TYPE_OOXML_XL` | Microsoft Office Open Excel 2007+ | -| `CL_TYPE_PART_HFSPLUS` | Apple HFS+ partition | -| `CL_TYPE_PDF` | Adobe PDF document | -| `CL_TYPE_POSIX_TAR` | TAR archive | -| `CL_TYPE_PS` | Postscript | -| `CL_TYPE_RAR` | RAR Archive | -| `CL_TYPE_RARSFX` | Self-Extracting RAR Archive | -| `CL_TYPE_RIFF` | Resource Interchange File Format container formatted file | -| `CL_TYPE_RTF` | Rich Text Format document | -| `CL_TYPE_SCRENC` | Files encrypted by ScrEnc malware | -| `CL_TYPE_SCRIPT` | Generic type for scripts (Javascript, Python, etc) | -| `CL_TYPE_SIS` | Symbian OS Software Installation Script Archive | -| `CL_TYPE_SWF` | Adobe Flash File (LZMA, Zlib, or uncompressed) | -| `CL_TYPE_TEXT_ASCII` | ASCII text | -| `CL_TYPE_TEXT_UTF16BE` | UTF-16BE text | -| `CL_TYPE_TEXT_UTF16LE` | UTF-16LE text | -| `CL_TYPE_TEXT_UTF8` | UTF-8 text | -| `CL_TYPE_TNEF` | Microsoft Outlook & Exchange email attachment format | -| `CL_TYPE_UUENCODED` | UUEncoded (Unix-to-Unix) binary file (Unix email attachment) | -| `CL_TYPE_XAR` | XAR Archive | -| `CL_TYPE_XDP` | Adobe XDP - Embedded PDF | -| `CL_TYPE_XML_HWP` | Hangul Word Processor XML (HWPML) Document | -| `CL_TYPE_XML_WORD` | Microsoft Word 2003 XML Document | -| `CL_TYPE_XML_XL` | Microsoft Excel 2003 XML Document | -| `CL_TYPE_XZ` | XZ Archive | -| `CL_TYPE_ZIP` | Zip Archive | -| `CL_TYPE_ZIPSFX` | Self-Extracting Zip Archive | diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/FunctionalityLevels.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/FunctionalityLevels.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/FunctionalityLevels.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/FunctionalityLevels.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -# Functionality Levels (FLEVELs) - -The Functionality Level (or FLEVEL) is an integer that signatures may use to define which versions of ClamAV the signature features support. It is up to the signature writers to select the correct FLEVEL or range of FLEVELs when writing a signature so that it does not cause failures in older versions of ClamAV. - -Setting appropriate FLEVELs in signatures is particularly crucial when using features added in the last 3-4 major release versions. - -## ClamAV Version to FLEVEL chart - -| flevel | version | release | new signature features | -|--------|---------|---------|------------------------------------------------------------------------| -| 41 | 0.95.0 | 3/2009 | Ignores use ign format (including line number). | -| 51 | 0.96.0 | 3/2010 | Bytecode & CDB sigs. Start using ign2. | -| 56 | 0.96.4 | 10/2010 | Min level for bytecode sigs. | -| 60 | 0.97.0 | 2/2011 | | -| 74 | 0.98.0 | 9/2013 | ISO9660 scanning support. All-match feature. | -| | | | Wild card bracket notation{} for body-based signatures. | -| | | | "SE" offset modifier. | -| | | | Target types 10 - 13: (PDF, (SWF) Flash, Java, Internal). | -| 76 | 0.98.1 | 1/2014 | XZ support and ForceToDisk scan option. | -| | | | Libxml2, XAR, DMG, HFS+/HFSX. | -| | | | FTM type 4 (in-buffer partition magic, analogous to type 0 for files). | -| 79 | 0.98.5 | 11/2014 | File properties (preclass). Target type 13: for preclass feature. | -| 81 | 0.99.0 | 11/2015 | Yara and PCRE support. Target type 14: non-listed types ("other"). | -| 82 | 0.99.1 | 2/2016 | Hangul Word Processor (HWP) type file parser. | -| 90 | 0.100 | 4/2018 | "Intermediates" logical sig expression option. | -| | | | MHTML and PostScript types. | -| | | | Substring wildcard (*) fix: order matters, substrings can't overlap. | -| 100 | 0.101 | 12/2018 | "Byte-Compare" Logical subsignature. Windows Shortcut (LNK) type. | - -For more inforamtion on ClamAV file type support, see the [File Types Reference](FileTypes.md). diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/HashSignatures.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/HashSignatures.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/HashSignatures.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/HashSignatures.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,67 +0,0 @@ -# File hash signatures - -The easiest way to create signatures for ClamAV is to use filehash checksums, however this method can be only used against static malware. - -## MD5 hash-based signatures - -To create a MD5 signature for `test.exe` use the `--md5` option of -sigtool: - -```bash -zolw@localhost:/tmp/test$ sigtool --md5 test.exe > test.hdb -zolw@localhost:/tmp/test$ cat test.hdb -48c4533230e1ae1c118c741c0db19dfb:17387:test.exe -``` - -That’s it! The signature is ready for use: - -```bash -zolw@localhost:/tmp/test$ clamscan -d test.hdb test.exe -test.exe: test.exe FOUND - ------------ SCAN SUMMARY ----------- -Known viruses: 1 -Scanned directories: 0 -Engine version: 0.92.1 -Scanned files: 1 -Infected files: 1 -Data scanned: 0.02 MB -Time: 0.024 sec (0 m 0 s) -``` - -You can change the name (by default sigtool uses the name of the file) and place it inside a `*.hdb` file. A single database file can include any number of signatures. To get them automatically loaded each time `clamscan`/`clamd` starts just copy the database file(s) into the local virus database directory (eg. `/usr/local/share/clamav`). - -*The hash-based signatures shall not be used for text files, HTML and any other data that gets internally preprocessed before pattern matching. If you really want to use a hash signature in such a case, run `clamscan` with `--debug` and `--leave-temps` flags as described above and create a signature for a preprocessed file left in `/tmp`. Please keep in mind that a hash signature will stop matching as soon as a single byte changes in the target file.* - -## SHA1 and SHA256 hash-based signatures - -ClamAV 0.98 has also added support for SHA1 and SHA256 file checksums. The format is the same as for MD5 file checksum. It can differentiate between them based on the length of the hash string in the signature. For best backwards compatibility, these should be placed inside a `*.hsb` file. The format is: - -``` -HashString:FileSize:MalwareName -``` - -## Hash signatures with unknown size - -ClamAV 0.98 has also added support for hash signatures where the size is not known but the hash is. It is much more performance-efficient to use signatures with specific sizes, so be cautious when using this feature. For these cases, the ’\*’ character can be used in the size field. To ensure proper backwards compatibility with older versions of ClamAV, these signatures must have a minimum functional level of 73 or higher. Signatures that use the wildcard size without this level set will be rejected as malformed. - -Sample .hsb signature matching any size: -``` - HashString:*:MalwareName:73 -``` -Sample .msb signature matching any size: -``` - *:PESectionHash:MalwareName:73 -``` - -## PE section based hash signatures - -You can create a hash signature for a specific section in a PE file. Such signatures shall be stored inside `.mdb` (MD5) and `.msb` files in the following format: - -``` - PESectionSize:PESectionHash:MalwareName -``` - -The easiest way to generate MD5 based section signatures is to extract target PE sections into separate files and then run sigtool with the option `--mdb` - -ClamAV 0.98 has also added support for SHA1 and SHA256 section based signatures. The format is the same as for MD5 PE section based signatures. It can differentiate between them based on the length of the hash string in the signature. For best backwards compatibility, these should be placed inside a `*.msb` file. diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/LogicalSignatures.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/LogicalSignatures.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/LogicalSignatures.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/LogicalSignatures.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,351 +0,0 @@ -# Logical signatures - -Logical signatures allow combining of multiple signatures in extended format using logical operators. They can provide both more detailed and flexible pattern matching. The logical sigs are stored inside `*.ldb` files in the following format: - -``` -SignatureName;TargetDescriptionBlock;LogicalExpression;Subsig0; -Subsig1;Subsig2;... -``` - -where: - -- `TargetDescriptionBlock` provides information about the engine and target file with comma separated `Arg:Val` pairs. For args where `Val` is a range, the minimum and maximum values should be expressed as `min-max`. - -- `LogicalExpression` specifies the logical expression describing the relationship between `Subsig0...SubsigN`. **Basis clause:** 0,1,...,N decimal indexes are SUB-EXPRESSIONS representing `Subsig0, Subsig1,...,SubsigN` respectively. **Inductive clause:** if `A` and `B` are SUB-EXPRESSIONS and `X, Y` are decimal numbers then `(A&B)`, `(A|B)`, `A=X`, `A=X,Y`, `A>X`, `A>X,Y`, `ACL_TYPE_*`: Specify one or more layers of file types containing the scanned file. _This is an alternative to using `Container`._ - - You may specify up to 16 layers of file types separated by ’`>`’ in top-down order. Note that the ’`>`’ separator is not needed if you only specify a single container. The last type should be the immediate container containing the malicious file. Unlike with the `Container` option, `CL_TYPE_ANY` can be used as a wildcard file type. (expr; 0.100.0) - - For a list of possible CL_TYPEs, refer to the [File Types Reference](ClamAVFileTypes.md). - -- `IconGroup1`: Icon group name 1 from .idb signature Required engine functionality (range; 0.96) - -- `IconGroup2`: Icon group name 2 from .idb signature Required engine functionality (range; 0.96) - -Modifiers for subexpressions: - -- `A=X`: If the SUB-EXPRESSION A refers to a single signature then this signature must get matched exactly X times; if it refers to a (logical) block of signatures then this block must generate exactly X matches (with any of its sigs). - -- `A=0` specifies negation (signature or block of signatures cannot be matched) - -- `A=X,Y`: If the SUB-EXPRESSION A refers to a single signature then this signature must be matched exactly X times; if it refers to a (logical) block of signatures then this block must generate X matches and at least Y different signatures must get matched. - -- `A>X`: If the SUB-EXPRESSION A refers to a single signature then this signature must get matched more than X times; if it refers to a (logical) block of signatures then this block must generate more than X matches (with any of its sigs). - -- `A>X,Y`: If the SUB-EXPRESSION A refers to a single signature then this signature must get matched more than X times; if it refers to a (logical) block of signatures then this block must generate more than X matches _and_ at least Y different signatures must be matched. - -- `AZ` above with the change of "more" to "less". - - If the SUB-EXPRESSION A refers to a single signature then this signature must get matched less than X times; if it refers to a (logical) block of signatures then this block must generate less than X matches (with any of its sigs). - -- `AX,Y`. If the SUB-EXPRESSION A refers to a single signature then this signature must get matched less than X times; if it refers to a (logical) block of signatures then this block must generate less than X matches _and_ at least Y different signatures must be matched. - -Examples: - -``` -Sig1;Target:0;(0&1&2&3)&(4|1);6b6f74656b;616c61;7a6f6c77;7374656 -6616e;deadbeef - -Sig2;Target:0;((0|1|2)>5,2)&(3|1);6b6f74656b;616c61;7a6f6c77;737 -46566616e - -Sig3;Target:0;((0|1|2|3)=2)&(4|1);6b6f74656b;616c61;7a6f6c77;737 -46566616e;deadbeef - -Sig4;Engine:51-255,Target:1;((0|1)&(2|3))&4;EP+123:33c06834f04100 -f2aef7d14951684cf04100e8110a00;S2+78:22??232c2d252229{-15}6e6573 -(63|64)61706528;S3+50:68efa311c3b9963cb1ee8e586d32aeb9043e;f9c58 -dcf43987e4f519d629b103375;SL+550:6300680065005c0046006900 -``` - -## Subsignature Modifiers - -ClamAV (clamav-0.99) supports a number of additional subsignature -modifiers for logical signatures. This is done by specifying `::` -followed by a number of characters representing the desired options. -Signatures using subsignature modifiers require `Engine:81-255` for -backwards-compatibility. - -- Case-Insensitive \[`i`\] - - Specifying the `i` modifier causes ClamAV to match all alphabetic hex bytes as case-insensitive. All patterns in ClamAV are case-sensitive by default. - -- Wide \[`w`\] - - Specifying the `w` causes ClamAV to match all hex bytes encoded with two bytes per character. Note this simply interweaves each character with NULL characters and does not truly support UTF-16 characters. Wildcards for ’wide’ subsignatures are not treated as wide (i.e. there can be an odd number of intermittent characters). This can be combined with `a` to search for patterns in both wide and ascii. - -- Fullword \[`f`\] - - Match subsignature as a fullword (delimited by non-alphanumeric characters). - -- Ascii \[`a`\] - - Match subsignature as ascii characters. This can be combined with `w` to search for patterns in both ascii and wide. - -Examples: - -``` -clamav-nocase-A;Engine:81-255,Target:0;0&1;41414141::i;424242424242::i - -matches 'AAAA'(nocase) and 'BBBBBB'(nocase) - -clamav-fullword-A;Engine:81-255,Target:0;0&1;414141;68656c6c6f::f - -matches 'AAA' and 'hello'(fullword) -clamav-fullword-B;Engine:81-255,Target:0;0&1;414141;68656c6c6f::fi - -matches 'AAA' and 'hello'(fullword nocase) - -clamav-wide-B2;Engine:81-255,Target:0;0&1;414141;68656c6c6f::wa - -matches 'AAA' and 'hello'(wide ascii) -clamav-wide-C0;Engine:81-255,Target:0;0&1;414141;68656c6c6f::iwfa - -matches 'AAA' and 'hello'(nocase wide fullword ascii) -``` - -## Special Subsignature Types - -### Macro subsignatures - -Introduced in ClamAV 0.96 - -Format: `${min-max}MACROID$` - -Macro subsignatures are used to combine a number of existing extended -signatures (`.ndb`) into a on-the-fly generated alternate string logical -signature (`.ldb`). Signatures using macro subsignatures require -`Engine:51-255` for backwards-compatibility. - -Example: - -``` - test.ldb: - TestMacro;Engine:51-255,Target:0;0&1;616161;${6-7}12$ - - test.ndb: - D1:0:$12:626262 - D2:0:$12:636363 - D3:0:$30:626264 -``` - -The example logical signature `TestMacro` is functionally equivalent -to: - -``` -`TestMacro;Engine:51-255,Target:0;0;616161{3-4}(626262|636363)` -``` - -- `MACROID` points to a group of signatures; there can be at most 32 macro groups. - - - In the example, `MACROID` is `12` and both `D1` and `D2` are members of macro group `12`. `D3` is a member of separate macro group `30`. - -- `{min-max}` specifies the offset range at which one of the group signatures should match; the offset range is relative to the starting offset of the preceding subsignature. This means a macro subsignature cannot be the first subsignature. - - - In the example, `{min-max}` is `{6-7}` and it is relative to the start of a `616161` match. - -- For more information and examples please see . - -### Byte Compare Subsignatures - -Introduced in ClamAV 0.101 - -Format: `subsigid_trigger(offset#byte_options#comparisons)` - -Byte compare subsignatures can be used to evaluate a numeric value at a given offset from the start of another (matched) subsignature within the same logical signature. These are executed after all other subsignatures within the logical subsignature are fired, with the exception of PCRE subsignatures. They can evaluate offsets only from a single referenced subsignature, and that subsignature must give a valid match for the evaluation to occur. - -- `subsigid_trigger` is a required field and may refer to any single non-PCRE, non-Byte Compare subsignature within the lsig. The byte compare subsig will evaluate if `subsigid_trigger` matches. Triggering on multiple subsigs or logic based triggering is not currently supported. - -- `offset` is a required field that consists of an `offset_modifier` and a numeric `offset` (hex or decimal offsets are okay). - - - `offset_modifier` can be either `>>` or `<<` where the former denotes a positive offset and the latter denotes a negative offset. The offset is calculated from the start of `subsigid_trigger`, which allows for byte extraction before the specified match, after the match, and within the match itself. - - - `offset` must be a positive hex or decimal value. This will be the number of bytes from the start of the referenced `subsigid_trigger` match within the file buffer to begin the comparison. - -- `byte_options` are used to specify the numeric type and endianess of the extracted byte sequence in that order as well as the number of bytes to be read. By default ClamAV will attempt to matchup up to the number of byte specified, unless the `e` (exact) option is specified or the numeric type is `b` (binary). This field follows the form `[h|d|a|i][l|b][e]num_bytes` - - - `h|d|a|i` where `h` specifies the byte sequence will be in hex, `d` decimal, `a` automatic detection of hex or decimal at runtime, and `i` signifies raw binary data. - - - `l|b` where `l` specifies the byte sequence will be in little endian order and `b` big endian. If decimal `d` is specified, big-endian is implied and using `l` will result in a malformed database error. - - - `e` specifies that ClamAV will only evaluate the comparison if it can extract the exact number of bytes specified. This option is implicitly declared when using the `i` flag. - - - `num_bytes` specifies the number of bytes to extract. This can be a hex or decimal value. If `i` is specified only 1, 2, 4, and 8 are valid options. - -- `comparisons` are a required field which denotes how to evaluate the extracted byte sequence. Each Byte Compare signature can have one or two `comparison_sets` separated by a comma. Each `comparison_set` consists of a `Comparison_symbol` and a `Comparison_value` and takes the form `Comparison_symbolComparison_value`. Thus, `comparisons` takes the form `comparison_set[,comparison_set]` - - - `Comparison_symbol` denotes the type of comparison to be done. The supported comparison symbols are `<`, `>`, `=`. - - - `Comparison_value` is a required field which must be a numeric hex or decimal value. If all other conditions are met, the byte compare subsig will evalutate the extracted byte sequence against this number based on the provided `comparison_symbol`. - -### PCRE subsignatures - -Introduced in ClamAV 0.99 - -Format: `Trigger/PCRE/[Flags]` - -PCRE subsignatures are used within a logical signature (`.ldb`) to specify regex matches that execute once triggered by a conditional based on preceding subsignatures. Signatures using PCRE subsignatures require `Engine:81-255` for backwards-compatibility. - -- `Trigger` is a required field that is a valid `LogicalExpression` and may refer to any subsignatures that precede this subsignature. Triggers cannot be self-referential and cannot refer to subsequent subsignatures. - -- `PCRE` is the expression representing the regex to execute. `PCRE` must be delimited by ’/’ and usage of ’/’ within the expression need to be escaped. For backward compatibility, ’;’ within the expression must be expressed as ’`\x3B`’. `PCRE` cannot be empty and (?UTF\*) control sequence is not allowed. If debug is specified, named capture groups are displayed in a post-execution report. - -- `Flags` are a series of characters which affect the compilation and execution of `PCRE` within the PCRE compiler and the ClamAV engine. This field is optional. - - - `g [CLAMAV_GLOBAL]` specifies to search for ALL matches of PCRE (default is to search for first match). NOTE: INCREASES the time needed to run the PCRE. - - - `r [CLAMAV_ROLLING]` specifies to use the given offset as the starting location to search for a match as opposed to the only location; applies to subsigs without maxshifts. By default, in order to facilatate normal ClamAV offset behavior, PCREs are auto-anchored (only attempt match on first offset); using the rolling option disables the auto-anchoring. - - - `e [CLAMAV_ENCOMPASS]` specifies to CONFINE matching between the specified offset and maxshift; applies only when maxshift is specified. Note: DECREASES time needed to run the PCRE. - - - `i [PCRE_CASELESS]` - - - `s [PCRE_DOTALL]` - - - `m [PCRE_MULTILINE]` - - - `x [PCRE_EXTENDED]` - - - `A [PCRE_ANCHORED]` - - - `E [PCRE_DOLLAR_ENODNLY]` - - - `U [PCRE_UNGREEDY]` - -Examples: - -``` -Find.All.ClamAV;Engine:81-255,Target:0;1;6265676c6164697427736e6f7462797465636f6465;0/clamav/g - -Find.ClamAV.OnlyAt.299;Engine:81-255,Target:0;2;7374756c747a67657473;7063726572656765786c6f6c;299:0&1/clamav/ - -Find.ClamAV.StartAt.300;Engine:81-255,Target:0;3;616c61696e;62756731393238;636c6f736564;300:0&1&2/clamav/r - -Find.All.Encompassed.ClamAV;Engine:81-255,Target:0;3;7768796172656e2774;796f757573696e67;79617261;200,300:0&1&2/clamav/ge - -Named.CapGroup.Pcre;Engine:81-255,Target:0;3;636f75727479617264;616c62756d;74657272696572;50:0&1&2/variable=(?.{16})end/gr - -Firefox.TreeRange.UseAfterFree;Engine:81-255,Target:0,Engine:81-255;0&1&2;2e766965772e73656c656374696f6e;2e696e76616c696461746553656c656374696f6e;0&1/\x2Eview\x2Eselection.*?\x2Etree\s*\x3D\s*null.*?\x2Einvalidate/smi - -Firefox.IDB.UseAfterFree;Engine:81-255,Target:0;0&1;4944424b657952616e6765;0/^\x2e(only|lowerBound|upperBound|bound)\x28.*?\x29.*?\x2e(lower|upper|lowerOpen|upperOpen)/smi - -Firefox.boundElements;Engine:81-255,Target:0;0&1&2;6576656e742e6 -26f756e64456c656d656e7473;77696e646f772e636c6f7365;0&1/on(load|click)\s*=\s*\x22?window\.close\s*\x28/si -``` - -## Signatures for Version Information (VI) metadata in PE files - -Starting with ClamAV 0.96 it is possible to easily match certain information built into PE files (executables and dynamic link libraries). Whenever you lookup the properties of a PE executable file in windows, you are presented with a bunch of details about the file itself. - -These info are stored in a special area of the file resources which goes under the name of `VS_VERSION_INFORMATION` (or versioninfo for short). It is divided into 2 parts. The first part (which is rather uninteresting) is really a bunch of numbers and flags indicating the product and file version. It was originally intended for use with installers which, after parsing it, should be able to determine whether a certain executable or library are to be upgraded/overwritten or are already up to date. Suffice to say, this approach never really worked and is generally never used. - -The second block is much more interesting: it is a simple list of key/value strings, intended for user information and completely ignored by the OS. For example, if you look at ping.exe you can see the company being *"Microsoft Corporation"*, the description *"TCP/IP Ping command"*, the internal name *"ping.exe"* and so on... Depending on the OS version, some keys may be given peculiar visibility in the file properties dialog, however they are internally all the same. - -To match a versioninfo key/value pair, the special file offset anchor `VI` was introduced. This is similar to the other anchors (like `EP` and `SL`) except that, instead of matching the hex pattern against a single offset, it checks it against each and every key/value pair in the file. The `VI` token doesn’t need nor accept a `+/-` offset like e.g. `EP+1`. As for the hex signature itself, it’s just the utf16 dump of the key and value. Only the `??` and `(aa|bb)` wildcards are allowed in the signature. Usually, you don’t need to bother figuring it out: each key/value pair together with the corresponding VI-based signature is printed by `clamscan` when the `--debug` option is given. - -For example `clamscan --debug freecell.exe` produces: - -```bash -[...] -Recognized MS-EXE/DLL file -in cli_peheader -versioninfo_cb: type: 10, name: 1, lang: 410, rva: 9608 -cli_peheader: parsing version info @ rva 9608 (1/1) -VersionInfo (d2de): 'CompanyName'='Microsoft Corporation' - -VI:43006f006d00700061006e0079004e0061006d006500000000004d006900 -630072006f0073006f0066007400200043006f00720070006f0072006100740 -069006f006e000000 -VersionInfo (d32a): 'FileDescription'='Entertainment Pack -FreeCell Game' - VI:460069006c006500440065007300630072006900700 -0740069006f006e000000000045006e007400650072007400610069006e006d -0065006e00740020005000610063006b0020004600720065006500430065006 -c006c002000470061006d0065000000 -VersionInfo (d396): 'FileVersion'='5.1.2600.0 (xpclient.010817 --1148)' - VI:460069006c006500560065007200730069006f006e00000000 -0035002e0031002e0032003600300030002e003000200028007800700063006 -c00690065006e0074002e003000310030003800310037002d00310031003400 -380029000000 -VersionInfo (d3fa): 'InternalName'='freecell' - VI:49006e007400 -650072006e0061006c004e0061006d006500000066007200650065006300650 -06c006c000000 -VersionInfo (d4ba): 'OriginalFilename'='freecell' - VI:4f007200 -6900670069006e0061006c00460069006c0065006e0061006d0065000000660 -0720065006500630065006c006c000000 -VersionInfo (d4f6): 'ProductName'='Sistema operativo Microsoft -Windows' - VI:500072006f0064007500630074004e0061006d00650000000 -000530069007300740065006d00610020006f00700065007200610074006900 -76006f0020004d006900630072006f0073006f0066007400ae0020005700690 -06e0064006f0077007300ae000000 -VersionInfo (d562): 'ProductVersion'='5.1.2600.0' - VI:50007200 -6f006400750063007400560065007200730069006f006e00000035002e00310 -02e0032003600300030002e0030000000 -[...] -``` - -Although VI-based signatures are intended for use in logical signatures you can test them using ordinary `.ndb` files. For example: - -``` - my_test_vi_sig:1:VI:paste_your_hex_sig_here -``` - -Final note. If you want to decode a VI-based signature into a human readable form you can use: - -```bash -echo hex_string | xxd -r -p | strings -el -``` - -For example: - -```bash -$ echo 460069006c0065004400650073006300720069007000740069006f006e -000000000045006e007400650072007400610069006e006d0065006e007400200 -05000610063006b0020004600720065006500430065006c006c00200047006100 -6d0065000000 | xxd -r -p | strings -el -FileDescription -Entertainment Pack FreeCell Game -``` - -## Icon Signatures for PE files - -While Icon Signatures are stored in a `.idb` file, they are a feature of Logical Signatures. - -ClamAV 0.96 includes an approximate/fuzzy icon matcher to help detecting malicious executables disguising themselves as innocent looking image files, office documents and the like. - -Icon matching is only triggered by Logical Signatures (`.ldb`) using the special attribute tokens `IconGroup1` or `IconGroup2`. These identify two (optional) groups of icons defined in a `.idb` database file. The format of the `.idb` file is: - -``` - ICONNAME:GROUP1:GROUP2:ICON_HASH -``` - -where: - -- `ICON_NAME` is a unique string identifier for a specific icon, - -- `GROUP1` is a string identifier for the first group of icons (`IconGroup1`) - -- `GROUP2` is a string identifier for the second group of icons (`IconGroup2`), - -- `ICON_HASH` is a fuzzy hash of the icon image - -The `ICON_HASH` field can be obtained from the debug output of libclamav. For example: - -```bash -LibClamAV debug: ICO SIGNATURE: -ICON_NAME:GROUP1:GROUP2:18e2e0304ce60a0cc3a09053a30000414100057e000afe0000e 80006e510078b0a08910d11ad04105e0811510f084e01040c080a1d0b0021000a39002a41 -``` diff -Nru clamav-0.101.4+dfsg/docs/UserManual/Signatures/PhishSigs.md clamav-0.102.1+dfsg/docs/UserManual/Signatures/PhishSigs.md --- clamav-0.101.4+dfsg/docs/UserManual/Signatures/PhishSigs.md 2019-08-20 16:08:49.000000000 +0000 +++ clamav-0.102.1+dfsg/docs/UserManual/Signatures/PhishSigs.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,682 +0,0 @@ -# PhishSigs - -Table of Contents -- [PhishSigs](#phishsigs) -- [Database file format](#database-file-format) - - [PDB format](#pdb-format) - - [GDB format](#gdb-format) - - [WDB format](#wdb-format) - - [Hints](#hints) - - [Examples of PDB signatures](#examples-of-pdb-signatures) - - [Examples of WDB signatures](#examples-of-wdb-signatures) - - [Example for how the URL extractor works](#example-for-how-the-url-extractor-works) - - [How matching works](#how-matching-works) - - [RealURL, displayedURL concatenation](#realurl-displayedurl-concatenation) - - [What happens when a match is found](#what-happens-when-a-match-is-found) - - [Extraction of realURL, displayedURL from HTML tags](#extraction-of-realurl-displayedurl-from-html-tags) - - [Example](#example) - - [Simple patterns](#simple-patterns) - - [Regular expressions](#regular-expressions) - - [Flags](#flags) -- [Introduction to regular expressions](#introduction-to-regular-expressions) - - [Special characters](#special-characters) - - [Character classes](#character-classes) - - [Escaping](#escaping) - - [Alternation](#alternation) - - [Optional matching, and repetition](#optional-matching-and-repetition) - - [Groups](#groups) -- [How to create database files](#how-to-create-database-files) - - [How to create and maintain the whitelist (daily.wdb)](#how-to-create-and-maintain-the-whitelist-dailywdb) - - [How to create and maintain the domainlist (daily.pdb)](#how-to-create-and-maintain-the-domainlist-dailypdb) - - [Dealing with false positives, and undetected phishing mails](#dealing-with-false-positives-and-undetected-phishing-mails) - - [False positives](#false-positives) - - [Undetected phish mails](#undetected-phish-mails) - -# Database file format - -## PDB format - -This file contains urls/hosts that are target of phishing attempts. It -contains lines in the following format: - -``` - R[Filter]:RealURL:DisplayedURL[:FuncLevelSpec] - H[Filter]:DisplayedHostname[:FuncLevelSpec] -``` - -- `R` - - regular expression, for the concatenated URL - -- `H` - - matches the `DisplayedHostname` as a simple pattern (literally, no regular expression) - - - the pattern can match either the full hostname - - - or a subdomain of the specified hostname - - - to avoid false matches in case of subdomain matches, the engine checks that there is a dot(`.`) or a space(` `) before the matched portion - -- `Filter` - - is ignored for R and H for compatibility reasons - -- `RealURL` - - is the URL the user is sent to, example: *href* attribute of an html anchor (*\ tag*) - -- `DisplayedURL` - - is the URL description displayed to the user, where its *claimed* they are sent, example: contents of an html anchor (*\ tag*) - -- `DisplayedHostname` - - is the hostname portion of the DisplayedURL - -- `FuncLevelSpec` - - an (optional) functionality level, 2 formats are possible: - - - `minlevel` all engines having functionality level \>= `minlevel` will load this line - - - `minlevel-maxlevel` engines with functionality level \(>=\) `minlevel`, and \(<\) `maxlevel` will load this line - -## GDB format - -This file contains URL hashes in the following format: - - S:P:HostPrefix[:FuncLevelSpec] - S:F:Sha256hash[:FuncLevelSpec] - S1:P:HostPrefix[:FuncLevelSpec] - S1:F:Sha256hash[:FuncLevelSpec] - S2:P:HostPrefix[:FuncLevelSpec] - S2:F:Sha256hash[:FuncLevelSpec] - S:W:Sha256hash[:FuncLevelSpec] - -- `S:` - - These are hashes for Google Safe Browsing - malware sites, and should not be used for other purposes. - -- `S2:` - - These are hashes for Google Safe Browsing - phishing sites, and should not be used for other purposes. - -- `S1:` - - Hashes for blacklisting phishing sites. Virus name: Phishing.URL.Blacklisted - -- `S:W:` - - Locally whitelisted hashes. - -- `HostPrefix` - - 4-byte prefix of the sha256 hash of the last 2 or 3 components of the hostname. If prefix doesn’t match, no further lookups are performed. - -- `Sha256hash` - - sha256 hash of the canonicalized URL, or a sha256 hash of its prefix/suffix according to the Google Safe Browsing “Performing Lookups” rules. There should be a corresponding `:P:HostkeyPrefix` entry for the hash to be taken into consideration. - -To see which hash/URL matched, look at the `clamscan --debug` output, and look for the following strings: `Looking up hash`, `prefix matched`, and `Hash matched`. Local whitelisting of .gdb entries can be done by creating a local.gdb file, and adding a line `S:W:`. - -## WDB format - -This file contains whitelisted url pairs It contains lines in the following format: - -``` - X:RealURL:DisplayedURL[:FuncLevelSpec] - M:RealHostname:DisplayedHostname[:FuncLevelSpec] -``` - -- `X` - - regular expression, for the *entire URL*, not just the hostname - - - The regular expression is by default anchored to start-of-line and end-of-line, as if you have used `^RegularExpression$` - - - A trailing `/` is automatically added both to the regex, and the input string to avoid false matches - - - The regular expression matches the *concatenation* of the RealURL, a colon(`:`), and the DisplayedURL as a single string. It doesn’t separately match RealURL and DisplayedURL\! - -- `M` - - matches hostname, or subdomain of it, see notes for H above - -## Hints - -- empty lines are ignored - -- the colons are mandatory - -- Don’t leave extra spaces on the end of a line\! - -- if any of the lines don’t conform to this format, clamav will abort with a Malformed Database Error - -- see section [Extraction-of-realURL](#Extraction-of-realURL,-displayedURL-from-HTML-tags) for more details on realURL/displayedURL - -## Examples of PDB signatures - -To check for phishing mails that target amazon.com, or subdomains of -amazon.com: - -``` - H:amazon.com -``` - -To do the same, but for amazon.co.uk: - -``` - H:amazon.co.uk -``` - -To limit the signatures to certain engine versions: - -``` - H:amazon.co.uk:20-30 - H:amazon.co.uk:20- - H:amazon.co.uk:0-20 -``` - -First line: engine versions 20, 21, ..., 29 can load it - -Second line: engine versions \>= 20 can load it - -Third line: engine versions \< 20 can load it - -In a real situation, you’d probably use the second form. A situation like that would be if you are using a feature of the signatures not available in earlier versions, or if earlier versions have bugs with your signature. Its neither case here, the above examples are for illustrative purposes only. - -## Examples of WDB signatures - -To allow amazon’s country specific domains and amazon.com, to mix domain names in DisplayedURL, and RealURL: - - X:.+\.amazon\.(at|ca|co\.uk|co\.jp|de|fr)([/?].*)?:.+\.amazon\.com([/?].*)?:17- - -Explanation of this signature: - -- `X:` - - this is a regular expression - -- `:17-` - - load signature only for engines with functionality level \>= 17 (recommended for type X) - -The regular expression is the following (X:, :17- stripped, and a / appended) - -``` - .+\.amazon\.(at|ca|co\.uk|co\.jp|de|fr)([/?].*)?:.+\.amazon\.com([/?].*)?/ -``` - -Explanation of this regular expression (note that it is a single regular expression, and not 2 regular expressions splitted at the :). - -- `.+` - - any subdomain of - -- `\.amazon\.` - - domain we are whitelisting (RealURL part) - -- `(at|ca|co\.uk|co\.jp|de|fr)` - - country-domains: at, ca, co.uk, co.jp, de, fr - -- `([/?].*)?` - - recomended way to end real url part of whitelist, this protects against embedded URLs (evilurl.example.com/amazon.co.uk/) - -- `:` - - RealURL and DisplayedURL are concatenated via a :, so match a literal : here - -- `.+` - - any subdomain of - -- `\.amazon\.com` - - whitelisted DisplayedURL - -- `([/?].*)?` - - recommended way to end displayed url part, to protect against embedded URLs - -- `/` - - automatically added to further protect against embedded URLs - -When you whitelist an entry make sure you check that both domains are owned by the same entity. What this whitelist entry allows is: Links claiming to point to amazon.com (DisplayedURL), but really go to country-specific domain of amazon (RealURL). - -## Example for how the URL extractor works - -Consider the following HTML file: - -```html - - - 1.displayedurl.example.com - - - 2 di

splayedurl.example.com - - - 3.nested.example.com - - 4.displayedurl.example.com - - -

- sometext - - - 5.form.nested.link-displayedurl.example.com - - - - 6.displ - - ayedurl.example.com - - -