Subject: All commits since the 5.43 release up to and including FILE5_43-145-g13aa1436
Upstream-Author: Christos Zoulas <christos@zoulas.com>
Last-Update: 2022-12-21

--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2022-12-14   9:24  Christos Zoulas <christos@zoulas.com>
+
+	* Handle nan's so that we don't get internal floating point exceptions
+	  when they are enabled (Vincent Mihalkovic)
+
+2022-10-23  10:21  Christos Zoulas <christos@zoulas.com>
+
+	* PR/397: Restore the ability to process files from stdin immediately.
+
+2022-09-20  17:12  Christos Zoulas <christos@zoulas.com>
+
+	* fixed various clustefuzz issues
+
+2022-09-19  15:54  Christos Zoulas <christos@zoulas.com>
+
+	* Fix error detection for decompression code (Vincent Mihalkovic)
+
+2022-09-15  13:50  Christos Zoulas <christos@zoulas.com>
+
+	* Add MAGIC_NO_COMPRESS_FORK and use it to produce a more
+	  meaningful error message if we are sandboxing.
+
+2022-09-15  10:45  Christos Zoulas <christos@zoulas.com>
+
+	* Add built-in lzip decompression support (Michal Gorny)
+
+2022-09-14  10:35  Christos Zoulas <christos@zoulas.com>
+
+	* Add built-in zstd decompression support (Martin Rodriguez Reboredo)
+
 2022-09-13  14:55  Christos Zoulas <christos@zoulas.com>
 
 	* release 5.43
@@ -229,7 +259,7 @@
 2019-12-15  22:13  Christos Zoulas <christos@zoulas.com>
     Document changes since the previous release:
 	- Always accept -S (no sandbox) even if we don't support sandboxing
-	- More syscalls elided for sandboxiing
+	- More syscalls elided for sandboxing
 	- For ELF dynamic means having an interpreter not just PT_DYNAMIC
 	- Check for large ELF session header offset
 	- When saving and restoring a locale, keep the locale name in our
@@ -1759,7 +1789,7 @@
 
 	* Magic format checks (Dr. Werner Fink)
 
-	* Magic format function improvent (Karl Chen)
+	* Magic format function improvement (Karl Chen)
 
 2006-05-03 11:11 Christos Zoulas <christos@astron.com>
 
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -39,11 +39,12 @@
 #include <stdlib.h>])
 AC_CACHE_CHECK(for daylight, ac_cv_var_daylight,
 [AC_LINK_IFELSE(
-[AC_LANG_PROGRAM([#include <time.h>],
+[AC_LANG_PROGRAM([#include <time.h>
+#include <stdlib.h>],
 [#if !HAVE_DECL_DAYLIGHT
 extern int daylight;
 #endif
-atoi(daylight);])], ac_cv_var_daylight=yes, ac_cv_var_daylight=no)])
+daylight = atoi("1");])], ac_cv_var_daylight=yes, ac_cv_var_daylight=no)])
   if test $ac_cv_var_daylight = yes; then
     AC_DEFINE(HAVE_DAYLIGHT,1,[HAVE_DAYLIGHT])
   fi
--- a/configure.ac
+++ b/configure.ac
@@ -49,6 +49,16 @@
 [AS_HELP_STRING([--disable-xzlib], [disable liblzma/xz compression support @<:@default=auto@:>@])])
 AC_MSG_RESULT($enable_xzlib)
 
+AC_MSG_CHECKING(for zstdlib support)
+AC_ARG_ENABLE([zstdlib],
+[AS_HELP_STRING([--disable-zstdlib], [disable zstdlib compression support @<:@default=auto@:>@])])
+AC_MSG_RESULT($enable_zstdlib)
+
+AC_MSG_CHECKING(for lzlib support)
+AC_ARG_ENABLE([lzlib],
+[AS_HELP_STRING([--disable-lzlib], [disable liblz (lzip) compression support @<:@default=auto@:>@])])
+AC_MSG_RESULT($enable_lzlib)
+
 AC_MSG_CHECKING(for libseccomp support)
 AC_ARG_ENABLE([libseccomp],
 [AS_HELP_STRING([--disable-libseccomp], [disable libseccomp sandboxing @<:@default=auto@:>@])])
@@ -112,6 +122,12 @@
 if test "$enable_xzlib" != "no"; then
   AC_CHECK_HEADERS(lzma.h)
 fi
+if test "$enable_zstdlib" != "no"; then
+  AC_CHECK_HEADERS(zstd.h zstd_errors.h)
+fi
+if test "$enable_lzlib" != "no"; then
+  AC_CHECK_HEADERS(lzlib.h)
+fi
 AC_CHECK_TYPE([sig_t],[AC_DEFINE([HAVE_SIG_T],1,[Have sig_t type])],,[#include <signal.h>])
 
 dnl Checks for typedefs, structures, and compiler characteristics.
@@ -180,6 +196,12 @@
 if test "$enable_xzlib" != "no"; then
   AC_CHECK_LIB(lzma, lzma_stream_decoder)
 fi
+if test "$enable_zstdlib" != "no"; then
+  AC_CHECK_LIB(zstd, ZSTD_createDStream)
+fi
+if test "$enable_lzlib" != "no"; then
+  AC_CHECK_LIB(lz, LZ_decompress_open)
+fi
 if test "$enable_libseccomp" != "no"; then
     AC_CHECK_LIB(seccomp, seccomp_init)
 fi
@@ -215,6 +237,22 @@
 if  test "$ac_cv_header_lzma_h$ac_cv_lib_lzma_lzma_stream_decoder" = "yesyes"; then
   AC_DEFINE([XZLIBSUPPORT], 1, [Enable xzlib compression support])
 fi
+if test "$enable_zstdlib" = "yes"; then
+  if test "$ac_cv_header_zstd_h$ac_cv_lib_zstd_ZSTD_createDStream" != "yesyes"; then
+    AC_MSG_ERROR([zstdlib support requested but not found])
+  fi
+fi
+if  test "$ac_cv_header_zstd_h$ac_cv_lib_zstd_ZSTD_createDStream" = "yesyes"; then
+  AC_DEFINE([ZSTDLIBSUPPORT], 1, [Enable zstdlib compression support])
+fi
+if test "$enable_lzlib" = "yes"; then
+  if test "$ac_cv_header_lzlib_h$ac_cv_lib_lz_LZ_decompress_open" != "yesyes"; then
+    AC_MSG_ERROR([lzlib support requested but not found])
+  fi
+fi
+if  test "$ac_cv_header_lzlib_h$ac_cv_lib_lz_LZ_decompress_open" = "yesyes"; then
+  AC_DEFINE([LZLIBSUPPORT], 1, [Enable lzlib compression support])
+fi
 
 AC_CONFIG_FILES([Makefile src/Makefile magic/Makefile tests/Makefile doc/Makefile python/Makefile libmagic.pc])
 AC_OUTPUT
--- a/doc/file.man
+++ b/doc/file.man
@@ -1,5 +1,5 @@
-.\" $File: file.man,v 1.144 2021/02/05 22:08:31 christos Exp $
-.Dd February 5, 2021
+.\" $File: file.man,v 1.147 2022/10/31 13:22:26 christos Exp $
+.Dd October 26, 2022
 .Dt FILE __CSECTION__
 .Os
 .Sh NAME
@@ -727,7 +727,7 @@
 It would be better if buffer managements was done when the file descriptor
 is available so we can seek around the file.
 One must be careful though because this has performance and thus security
-considerations, because one can slow down things by repeateadly seeking.
+considerations, because one can slow down things by repeatedly seeking.
 .Pp
 There is support now for keeping separate buffers and having offsets from
 the end of the file, but the internal buffer management still needs an
--- a/doc/libmagic.man
+++ b/doc/libmagic.man
@@ -1,6 +1,6 @@
-.\" $File: libmagic.man,v 1.45 2019/06/08 22:16:24 christos Exp $
+.\" $File: libmagic.man,v 1.46 2022/09/15 16:54:14 christos Exp $
 .\"
-.\" Copyright (c) Christos Zoulas 2003, 2018.
+.\" Copyright (c) Christos Zoulas 2003, 2018, 2022
 .\" All Rights Reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 8, 2019
+.Dd September 15, 2022
 .Dt LIBMAGIC 3
 .Os
 .Sh NAME
@@ -143,6 +143,8 @@
 Don't check for
 .Dv EMX
 application type (only on EMX).
+.It Dv MAGIC_NO_COMPRESS_FORK
+Don't allow decompressors that use fork.
 .It Dv MAGIC_NO_CHECK_CDF
 Don't get extra information on MS Composite Document Files.
 .It Dv MAGIC_NO_CHECK_COMPRESS
--- a/doc/magic.man
+++ b/doc/magic.man
@@ -1,5 +1,5 @@
-.\" $File: magic.man,v 1.100 2022/09/10 13:19:26 christos Exp $
-.Dd September 10, 2022
+.\" $File: magic.man,v 1.101 2022/10/09 18:51:04 christos Exp $
+.Dd October 9, 2022
 .Dt MAGIC __FSECTION__
 .Os
 .\" install as magic.4 on USG, magic.5 on V7, Berkeley and Linux systems.
@@ -68,54 +68,52 @@
 A 64-bit double precision IEEE floating point number in this machine's native byte order.
 .It Dv string
 A string of bytes.
-The string type specification can be optionally followed
-by /[WwcCtbTf]*.
-The
-.Dq W
-flag compacts whitespace in the target, which must
-contain at least one whitespace character.
-If the magic has
-.Dv n
-consecutive blanks, the target needs at least
-.Dv n
-consecutive blanks to match.
-The
-.Dq w
-flag treats every blank in the magic as an optional blank.
-The
-.Dq f
-flags requires that the matched string is a full word, not a partial word match.
-The
-.Dq c
-flag specifies case insensitive matching: lower case
+The string type specification can be optionally followed by a /<width> 
+option and optionally followed by a set of flags /[bCcftTtWw]*.
+The width limits the number of characters to be copied.
+Zero means all characters.
+The following flags are supported:
+.Bl -tag -width B -compact -offset XXXX
+.It b
+Force binary file test.
+.It C
+Use upper case insensitive matching: upper case
 characters in the magic match both lower and upper case characters in the
-target, whereas upper case characters in the magic only match upper case
+target, whereas lower case characters in the magic only match upper case
 characters in the target.
-The
-.Dq C
-flag specifies case insensitive matching: upper case
+.It c
+Use lower case insensitive matching: lower case
 characters in the magic match both lower and upper case characters in the
-target, whereas lower case characters in the magic only match upper case
+target, whereas upper case characters in the magic only match upper case
 characters in the target.
 To do a complete case insensitive match, specify both
 .Dq c
 and
 .Dq C .
-The
-.Dq t
-flag forces the test to be done for text files, while the
-.Dq b
-flag forces the test to be done for binary files.
-The
-.Dq T
-flag causes the string to be trimmed, i.e. leading and trailing whitespace
+.It f
+Require that the matched string is a full word, not a partial word match.
+.It T
+Trim the string, i.e. leading and trailing whitespace
+.It t
+Force text file test.
+.It W
+Compact whitespace in the target, which must
+contain at least one whitespace character.
+If the magic has
+.Dv n
+consecutive blanks, the target needs at least
+.Dv n
+consecutive blanks to match.
+.It w
+Treat every blank in the magic as an optional blank.
 is deleted before the string is printed.
+.El
 .It Dv pstring
 A Pascal-style string where the first byte/short/int is interpreted as the
 unsigned length.
 The length defaults to byte and can be specified as a modifier.
 The following modifiers are supported:
-.Bl -tag -compact -width B
+.Bl -tag -width B -compact -offset XXXX
 .It B
 A byte length (default).
 .It H
--- a/magic/Magdir/algol68
+++ b/magic/Magdir/algol68
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: algol68,v 1.4 2021/08/15 06:00:55 christos Exp $
+# $File: algol68,v 1.6 2022/11/06 18:36:55 christos Exp $
 # algol68:  file(1) magic for Algol 68 source
 #
 # URL: 		https://en.wikipedia.org/wiki/ALGOL_68
@@ -9,14 +9,8 @@
 0	search/8192	(input,
 >0	use		algol_68
 # graph_2d.a68
-0	regex/4006	\^PROC
-#>&-4	string		x			\b, dBase or Algol "%s"
-# most xBase scripts *.prg with PROCEDURE like: Areacode BarCount Def_mens Vendors
-#>&-4	string		=PROCEDURE		\b, dBase PROCEDURE
-# skip xBase program scripts *.prg with PROCEDURE keyword
-# keyword proc probably followed by white space used to specify algol procedures
->&-4	string		!PROCEDURE
->>0	use		algol_68
+0	regex/4006	\^PROC[[:space:]][a-zA-Z0-9_[:space:]]*[[:space:]]=
+>0	use		algol_68
 0	regex/1024	\bMODE[\t\ ]
 >0	use		algol_68
 0	regex/1024	\bMODE[\t\ ]
--- a/magic/Magdir/animation
+++ b/magic/Magdir/animation
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: animation,v 1.90 2022/08/16 11:16:39 christos Exp $
+# $File: animation,v 1.91 2022/11/30 20:34:47 christos Exp $
 # animation:  file(1) magic for animation/movie formats
 #
 # animation formats
@@ -938,6 +938,15 @@
 !:mime  video/MP2T
 !:ext	ts
 
+# Blu-ray disc Audio-Video MPEG-2 transport stream
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://en.wikipedia.org/wiki/MPEG_transport_stream
+# Note: similar to ISO 13818.1 but with 4 extra bytes per packets
+4	belong&0xFF5FFF10	=0x47400010
+>196	byte			=0x47		BDAV MPEG-2 Transport Stream (M2TS)
+!:mime	video/MP2T
+!:ext	m2ts/mts
+
 # DIF digital video file format <mpruett@sgi.com>
 0	belong&0xffffff00	0x1f070000      DIF
 !:mime  video/x-dv
--- a/magic/Magdir/apple
+++ b/magic/Magdir/apple
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: apple,v 1.45 2021/04/26 15:56:00 christos Exp $
+# $File: apple,v 1.47 2022/12/09 15:48:14 christos Exp $
 # apple:  file(1) magic for Apple file formats
 #
 0	search/1/t	FiLeStArTfIlEsTaRt	binscii (apple ][) text
@@ -11,26 +11,48 @@
 0	belong		0x00051600		AppleSingle encoded Macintosh file
 0	belong		0x00051607		AppleDouble encoded Macintosh file
 
+# Type: Apple Emulator A2R format
+# From: Greg Wildman <greg@apple2.org.za>
+# Ref: https://applesaucefdc.com/a2r2-reference/
+# Ref: https://applesaucefdc.com/a2r/
+0	string		A2R
+>3	string		\x31\xFF\x0A\x0D\x0A	Applesauce A2R 1.x Disk Image
+>3	string		\x32\xFF\x0A\x0D\x0A	Applesauce A2R 2.x Disk Image
+>3	string		\x33\xFF\x0A\x0D\x0A	Applesauce A2R 3.x Disk Image
+>8	string		INFO
+>>49	byte		01			\b, 5.25″ SS 40trk
+>>49	byte		02			\b, 3.5″ DS 80trk
+>>49	byte		03			\b, 5.25″ DS 80trk
+>>49	byte		04			\b, 5.25″ DS 40trk
+>>49	byte		05			\b, 3.5″ DS 80trk
+>>49	byte		06			\b, 8″ DS
+>>50	byte		01			\b, write protected
+>>51	byte		01			\b, cross track synchronized
+>>17	string/T	x			\b, %.32s
+
 # Type: Apple Emulator WOZ format
 # From: Greg Wildman <greg@apple2.org.za>
 # Ref: https://applesaucefdc.com/woz/reference/
 # Ref: https://applesaucefdc.com/woz/reference2/
-#
-# Note: The following test are mostly identical. I would rather not
-# use a regex to identify the WOZ format number.
-0	string		WOZ1
->4	string		\xFF\x0A\x0D\x0A	Apple ][ WOZ 1.0 Disk Image
+0	string		WOZ
+>3	string		\x31\xFF\x0A\x0D\x0A	Apple ][ WOZ 1.0 Disk Image
+>3	string		\x32\xFF\x0A\x0D\x0A	Apple ][ WOZ 2.0 Disk Image
 >12	string		INFO
 >>21	byte		01			\b, 5.25 inch
 >>21	byte		02			\b, 3.5 inch
 >>22	byte		01			\b, write protected
 >>23	byte		01			\b, cross track synchronized
 >>25	string/T	x			\b, %.32s
-0	string		WOZ2
->4	string		\xFF\x0A\x0D\x0A	Apple ][ WOZ 2.0 Disk Image
+
+# Type: Apple Macintosh Emulator MOOF format
+# From: Greg Wildman <greg@apple2.org.za>
+# Ref: https://applesaucefdc.com/moof-reference/
+0	string		MOOF
+>4	string		\xFF\x0A\x0D\x0A	Apple Macintosh MOOF Disk Image
 >12	string		INFO
->>21	byte		01			\b, 5.25 inch
->>21	byte		02			\b, 3.5 inch
+>>21	byte		01			\b, SSDD GCR (400K)
+>>21	byte		02			\b, DSDD GCR (800K)
+>>21	byte		03			\b, DSHD MFM (1.44M)
 >>22	byte		01			\b, write protected
 >>23	byte		01			\b, cross track synchronized
 >>25	string/T	x			\b, %.32s
@@ -43,29 +65,79 @@
 >0x400		string	\x00\x00\x03\x00
 >>0x404		byte	&0xF0
 >>>0x405	string	x			\b, Volume /%s
->>>0x429	leshort	x			\b, %u Blocks
+>>>0x429	uleshort	x		\b, %u Blocks
 # ProDOS ordered ?
 >0xb00		string	\x00\x00\x03\x00
 >>0xb04		byte	&0xF0
 >>>0xb05	string	x			\b, Volume /%s
->>>0xb29	leshort	x			\b, %u Blocks
+>>>0xb29	uleshort	x		\b, %u Blocks
 #
-# DOS3.3 boot loader?
-0		string	\x01\xA5\x27\xC9\x09\xD0\x18\xA5\x2B
->0x11001	string	\x11\x0F\x03	Apple DOS 3.3 Image
->>0x11006	byte	x		\b, Volume %u
->>0x11034	byte	x		\b, %u Tracks
->>0x11035	byte	x		\b, %u Sectors
->>0x11036	leshort	x		\b, %u bytes per sector
-# DOS3.2 ?
->0x11001	string	\x11\x0C\x02	Apple DOS 3.2 Image
->>0x11006	byte	x		\b, Volume %u
->>0x11034	byte	x		\b, %u Tracks
->>0x11035	byte	x		\b, %u Sectors
->>0x11036	leshort	x		\b, %u bytes per sector
-# DOS3.1 ?
->0x11001	string	\x11\x0C\x01
->>0x11c00	string	\x00\x11\x0B	Apple DOS 3.1 Image
+# Proboot HD
+0		string	\x01\x8A\x48\xD8\x2C\x82\xC0\x8D\x0E\xC0\x8D\x0C	Apple ProDOS ProBoot Image
+>0x400		string	\x00\x00\x03\x00
+>>0x404		byte	&0xF0
+>>>0x405	string	x			\b, Volume /%s
+>>>0x429	uleshort	x		\b, %u Blocks
+>0xb00		string	\x00\x00\x03\x00
+>>0xb04		byte	&0xF0
+>>>0xb05	string	x			\b, Volume /%s
+>>>0xb29	uleshort	x		\b, %u Blocks
+0		string	\x01\xA8\x8A\x20\x7B\xF8\x29\x07\x09\xC0\x99\x30	Apple ProDOS ProBoot Image
+>0x400		string	\x00\x00\x03\x00
+>>0x404		byte	&0xF0
+>>>0x405	string	x			\b, Volume /%s
+>>>0x429	uleshort	x		\b, %u Blocks
+>0xb00		string	\x00\x00\x03\x00
+>>0xb04		byte	&0xF0
+>>>0xb05	string	x			\b, Volume /%s
+>>>0xb29	uleshort	x		\b, %u Blocks
+0		string	\x01\x4A\xD0\x34\xE6\x3D\x8A\x20\x7B\xF8\x09\xC0	Apple ProDOS ProBoot Image
+>0x400		string	\x00\x00\x03\x00
+>>0x404		byte	&0xF0
+>>>0x405	string	x			\b, Volume /%s
+>>>0x429	uleshort	x		\b, %u Blocks
+>0xb00		string	\x00\x00\x03\x00
+>>0xb04		byte	&0xF0
+>>>0xb05	string	x			\b, Volume /%s
+>>>0xb29	uleshort	x		\b, %u Blocks
+#
+# ProDOS formatted
+0		string	\x01\xBD\x88\xC0\x20\x2F\xFB\x20\x58\xFC\x20\x40	Apple ProDOS Unbootable Image
+>0x400		string	\x00\x00\x03\x00
+>>0x404		byte	&0xF0
+>>>0x405	string	x			\b, Volume /%s
+>>>0x429	uleshort	x		\b, %u Blocks
+>0xb00		string	\x00\x00\x03\x00
+>>0xb04		byte	&0xF0
+>>>0xb05	string	x			\b, Volume /%s
+>>>0xb29	uleshort	x		\b, %u Blocks
+0		string	\x01\x38\xB0\x03\x4C\x1C\x09\x78\x86\x43\xC9\x03	Apple ProDOS Unbootable Image
+>0x400		string	\x00\x00\x03\x00
+>>0x404		byte	&0xF0
+>>>0x405	string	x			\b, Volume /%s
+>>>0x429	uleshort	x		\b, %u Blocks
+>0xb00		string	\x00\x00\x03\x00
+>>0xb04		byte	&0xF0
+>>>0xb05	string	x			\b, Volume /%s
+>>>0xb29	uleshort	x		\b, %u Blocks
+#
+# DOS3 boot loader
+0		string	\x01\xA5\x27\xC9\x09\xD0
+>0x11001	byte	0x11
+>>0x11003	ubyte	x		Apple DOS 3.%u Image
+>>0x11006	ubyte	x		\b, Volume #%03u
+>>0x11034	ubyte	x		\b, %u Tracks
+>>0x11035	ubyte	x		\b, %u Sectors
+>>0x11036	uleshort	x		\b, %u bytes per sector
+#
+# DOS3 uninitialized disk
+0		string	\x01\xA6\x2B\xBD\x88\xC0\x8A\x4A\x4A
+>0x11001	byte	0x11
+>>0x11003	ubyte	x	Apple DOS 3.%u Unbootable Image
+>>>0x11006	ubyte	x		\b, Volume #%03u
+>>>0x11034	ubyte	x		\b, %u Tracks
+>>>0x11035	ubyte	x		\b, %u Sectors
+>>>0x11036	uleshort	x		\b, %u bytes per sector
 #
 # Pascal boot loader?
 0		string	\x01\xE0\x60\xF0\x03\x4C\xE3\x08\xAD
@@ -112,9 +184,70 @@
 >>0x440		string	\x00\x00\x03\x00
 >>>0x444	byte	&0xF0
 >>>>0x445	string	x		\b, Volume /%s
->>>>0x469	leshort	x		\b, %u Blocks
+>>>>0x469	uleshort	x		\b, %u Blocks
 >0xc		byte	02		\b, NIB data
 
+# Type: Peter Ferrie QBoot
+# From: Greg Wildman <greg@apple2.org.za>
+# Ref: https://github.com/peterferrie/qboot
+0	string	\x01\x4A\xA8\x69\x0F\x85\x27\xC9
+>8	string	\x12\xF0\x10\xE6\x3D\x86\xDA\x8A	Apple ][ QBoot Image
+
+# Type: Peter Ferrie 0Boot
+# From: Greg Wildman <greg@apple2.org.za>
+# Ref: https://github.com/peterferrie/0boot
+0	string	\x01\x4A\xA8\x69\x0F\x85\x27\xC9
+>8	string	\x12\xF0\x10\xE6\x3D\x86\xDA\x8A	Apple ][ 0Boot Image
+
+# Different proprietary boot sectors
+0	string	\x01\x0F\x21\x74\x00\x01\x6B\x00\x02\x30\x81\x5D	Apple ][ Disk Image
+0	string	\x01\x20\x58\xFC\xA2\x00\x8E\x78\x04\x8E\xF4\x03	Apple ][ Disk Image
+0	string	\x01\x20\x58\xFC\xAD\x51\xC0\xAD\x54\xC0\xA6\x2B	Apple ][ Disk Image
+0	string	\x01\x20\x89\xFE\x20\x93\xFE\xA6\x2B\xBD\x88\xC0	Apple ][ Disk Image
+0	string	\x01\x20\x93\xFE\x20\x89\xFE\x4C\x25\x08\x68\x85	Apple ][ Disk Image
+0	string	\x01\x20\x93\xFE\x20\x89\xFE\x4C\x2D\x08\x68\x85	Apple ][ Disk Image
+0	string	\x01\x38\x90\x2A\xC9\x01\xF0\x33\xA8\xC8\xC0\x10	Apple ][ Disk Image
+0	string	\x01\x38\xB0\x03\x4C\x32\xA1\x87\x43\xC9\x03\x08	Apple ][ Disk Image
+0	string	\x01\x4C\x04\x08\xA9\x2A\x8D\x02\x08\x86\x2B\xEE	Apple ][ Disk Image
+0	string	\x01\x4C\x60\x08\x09\xD0\x18\xA5\x2B\x4A\x4A\x4A	Apple ][ Disk Image
+0	string	\x01\x4C\x92\x08\x01\x08\xA2\x00\xB5\x00\x9D\x00	Apple ][ Disk Image
+0	string	\x01\x4C\xB3\x08\x09\xD0\x18\xA5\x2B\x4A\x4A\x4A	Apple ][ Disk Image
+0	string	\x01\x8D\xFB\x03\x8E\xFC\x03\x8C\xFD\x03\x8A\x29	Apple ][ Disk Image
+0	string	\x01\xA2\xFF\x9A\xD8\x20\x20\x08\x20\x34\x08\xAD	Apple ][ Disk Image
+0	string	\x01\xA5\x27\xBD\x88\xC0\x2C\x10\xC0\xA2\x00\xA9	Apple ][ Disk Image
+0	string	\x01\xA5\x2B\xAE\x51\xC0\xEA\xAA\xBD\x88\xC0\x20	Apple ][ Disk Image
+0	string	\x01\xA6\x27\xBD\x0B\x08\x48\xBD\x0A\x08\x48\x85	Apple ][ Disk Image
+0	string	\x01\xA6\x2B\xBD\x88\xC0\x20\x58\xFC\xA9\x01\x85	Apple ][ Disk Image
+0	string	\x01\xA6\x2B\xBD\x88\xC0\x20\x58\xFC\xA9\x25\x85	Apple ][ Disk Image
+0	string	\x01\xA8\xC0\x0F\x90\x16\xF0\x12\xA0\xFF\x18\xAD	Apple ][ Disk Image
+0	string	\x01\xA9\x00\x85\xF0\xA9\x04\x85\xF1\xA0\x00\xA9	Apple ][ Disk Image
+0	string	\x01\xA9\x5C\x8D\xF2\x03\xA9\xC6\x8D\xF3\x03\x49	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\x20\x2F\xFB\x20\x58\xFC	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\x20\x49\x08\xA9\x0A\x85	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\x2C\x82\xC0\xBD\x88\xC0	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\x86\x43\x8A\x4A\x4A\x4A	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\xA2\x00\x86\xFF\xB5\x00	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\xA2\x00\xB5\x00\x9D\x00	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\xA9\xB2\x8D\xF2\x03\xA9	Apple ][ Disk Image
+0	string	\x01\xA9\x60\x8D\x01\x08\xA9\xFF\x8D\xF3\x03\x8D	Apple ][ Disk Image
+0	string	\x01\xAC\x00\x08\xF0\x19\xB9\x30\x08\x85\x3D\xCE	Apple ][ Disk Image
+0	string	\x01\xAC\x23\x08\x30\x2E\xB9\x24\x08\x85\x3D\xCE	Apple ][ Disk Image
+0	string	\x01\xAD\x00\x08\xC9\x09\xB0\x20\x69\x02\x8D\x00	Apple ][ Disk Image
+0	string	\x01\xB0\x00\xA9\x3C\x8D\x02\x08\x86\x2B\x8A\x4A	Apple ][ Disk Image
+0	string	\x01\xB0\x00\xA9\x3C\x8D\x02\x08\xA9\xF5\x8D\xF2	Apple ][ Disk Image
+0	string	\x01\xB0\x00\xA9\x3F\x8D\x02\x08\x86\x2B\x8E\xF4	Apple ][ Disk Image
+0	string	\x01\xB0\x00\xA9\x48\x8D\x02\x08\x86\x2B\x8E\xF4	Apple ][ Disk Image
+0	string	\x01\xBD\x88\xC0\x8A\x4A\x4A\x4A\x4A\x09\xC0\x8D	Apple ][ Disk Image
+0	string	\x01\xBD\x88\xC0\x8A\x4A\x4A\x4A\x4A\x8D\x2F\x08	Apple ][ Disk Image
+0	string	\x01\xD8\x2C\x81\xC0\xA9\x60\x4D\x58\xFF\xD0\xFE	Apple ][ Disk Image
+0	string	\x01\xD8\x78\xBD\x88\xC0\xA9\xFD\x85\x37\x85\x39	Apple ][ Disk Image
+0	string	\x01\xE0\x60\xF0\x03\x4C\x16\x09\xAD\x00\x08\xC9	Apple ][ Disk Image
+0	string	\x01\xE0\x60\xF0\x03\x4C\xCB\x08\xAD\x00\x08\xC9	Apple ][ Disk Image
+0	string	\x01\xE0\x60\xF0\x03\x4C\xEE\x08\xAD\x00\x08\xC9	Apple ][ Disk Image
+0	string	\x01\xE0\x60\xF0\x03\x4C\xEF\x08\xAD\x00\x08\xC9	Apple ][ Disk Image
+0	string	\x01\xE0\x70\xB0\x04\xE0\x40\xB0\x39\xBD\x88\xC0	Apple ][ Disk Image
+0	string	\x01\xEA\x8D\xF4\x03\xA9\x60\x9D\x88\xC0\x8D\x51	Apple ][ Disk Image
+
 # magic for Newton PDA package formats
 # from Ruda Moura <ruda@helllabs.org>
 0	string	package0	Newton package, NOS 1.x,
@@ -491,9 +624,107 @@
 # Usually not in separate files, but have either filename rsrc with
 # no extension, or a filename corresponding to another file, with
 # extensions rsr/rsrc
+# URL:		http://fileformats.archiveteam.org/wiki/Macintosh_resource_file
+#		https://en.wikipedia.org/wiki/Resource_fork
+# Reference:	https://github.com/kreativekorp/ksfl/wiki/Macintosh-Resource-File-Format
+#		http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/MoreMacintoshToolbox.pdf
+#		https://formats.kaitai.io/resource_fork/
+# Update:	Joerg Jenderek
+# Note:		verified often by command like `deark -m macrsrc Icon_.rsrc`
+# offset of resource data; usually starts at offset 0x0100
 0	string  \000\000\001\000
->4	leshort 0
->>16	lelong  0			Apple HFS/HFS+ resource fork
+# skip NPETraceSession.etl with invalid "low" map offset 0
+>4	ubelong	>0xFF
+# skip few Atari DEGAS Elite bitmap (eil2.pi1 nastro.pi1) with ivalid "high" 0x6550766 0x7510763 map length
+>>12	ubelong	<0x8001
+# most examples with zeroed system reserved field
+>>>16	lelong  =0
+>>>>0	use	apple-rsr
+# few samples with not zeroed system reserved field like: Empty.rsrc.rsr OpenSans-CondBold.dfont
+>>>16	lelong  !0
+# resource fork variant with not zeroed system reserved field and copy of header 
+>>>>(4.L)	ubelong	0x100
+# GRR: the line above only works if in ../../src/file.h FILE_BYTES_MAX is raised from 1 MiB above 0x6ab0f4 (HelveticaNeue.dfont)
+>>>>>0	use	apple-rsr
+# data fork variant with not zeroed system reserved field and no copy of header 
+>>>>(4.L)	ubelong	0
+>>>>>0	use	apple-rsr
+# Note: moved and merged from ./macintosh
+# From: Adam Buchbinder <adam.buchbinder@gmail.com>
+# URL: https://en.wikipedia.org/wiki/Datafork_TrueType
+# Derived from the 'fondu' and 'ufond' source code (fondu.sf.net). 'sfnt' is
+# TrueType; 'POST' is PostScript. 'FONT' and 'NFNT' sometimes appear, but I
+# don't know what they mean.
+#	display information about Mac OSX datafork font DFONT
+0	name		apple-dfont
+>(4.L+30)	ubelong x		Mac OSX datafork font,
+# https://en.wikipedia.org/wiki/Datafork_TrueType
+!:mime		application/x-dfont
+!:ext		dfont
+# https://exiftool.org/TagNames/RSRC.html
+>(4.L+30)	ubelong	0x73666e74	TrueType
+>(4.L+30)	ubelong	0x464f4e54	'FONT'
+>(4.L+30)	ubelong	0x4e464e54	'NFNT'
+>(4.L+30)	ubelong	0x504f5354	PostScript
+>(4.L+30)	ubelong	0x464f4e44	'FOND'
+>(4.L+30)	ubelong	0x76657273	'vers'
+#	display information about Macintosh resource
+0	name		apple-rsr
+>(4.L+30)	ubelong	0x73666e74
+>>0	use	apple-dfont
+>(4.L+30)	ubelong	0x464f4e54
+>>0	use	apple-dfont
+>(4.L+30)	ubelong	0x4e464e54
+>>0	use	apple-dfont
+>(4.L+30)	ubelong	0x504f5354
+>>0	use	apple-dfont
+>(4.L+30)	ubelong	0x464f4e44
+>>0	use	apple-dfont
+>(4.L+30)	ubelong	0x76657273
+>>0	use	apple-dfont
+>(4.L+30)	default	x		Apple HFS/HFS+ resource fork
+#!:mime		application/octet-stream
+!:mime		application/x-apple-rsr
+!:ext		rsrc/rsr
+# offset to resource data; usually starts at offset 0x0100
+>0		ubelong		!0x100	\b, data offset %#x
+# offset to resource map; positive but not nil like in NPETraceSession.etl
+>4		ubelong		x	\b, map offset %#x
+# length of resource map; positive with 32K limitation but not
+# nil like in NPETraceSession.etl or high like 0x7510763 in nastro.pi1
+>12		ubelong		x	\b, map length %#x
+# length of resource data; positive but not nil like in NPETraceSession.etl
+>8		ubelong		x	\b, data length %#x
+# reserved 112 bytes for system use; apparently often nil, but 8fd20000h in Empty.rsrc.rsr and 0x00768c2b in OpenSans-CondBold.dfont
+>16		ubelong		!0	\b, at 16 %#8.8x
+# https://fontforge.org/docs/techref/macformats.html
+# jump to resource map
+# a copy of resource header or 16 bytes of zeros for data fork
+#>(4.L)		ubelong		x	\b, DATA offset %#x
+#>(4.L+4) 	ubelong 	x	\b, MAP offset %#x
+#>(4.L+8) 	ubelong 	x	\b, DATA length %#x
+#>(4.L+12) 	ubelong 	x	\b, MAP length %#x
+# nextResourceMap; handle to next resource map; used by the Resource Manager for internal bookkeeping; should be zero
+>(4.L+16) 	ubelong		!0	\b, nextResourceMap %#x
+# fileRef; file reference number; used by the Resource Manager for internal bookkeeping; should be zero
+>(4.L+20)	ubeshort	!0	\b, fileRef %#x
+# attributes; Resource fork attributes (80h~read-only 40h~compression needed 20h~changed); other bits are reserved and should be zero
+>(4.L+22)	ubeshort	!0	\b, attributes %#x
+# typeListOffset; offset from resource map to start of type list like: 1Ch
+>(4.L+24)	ubeshort	x	\b, list offset %#x
+# nameListOffset; offset from esource map to start of name list like: 32h 46h 56h (XLISP.RSR XLISPTIN.RSR) 13Eh (HelveticaNeue.dfont)
+>(4.L+26)	ubeshort	x	\b, name offset %#x
+# typeCount; number of types in the map minus 1; If there are no resources, this is 0xFFFF
+>(4.L+28)	beshort+1	>0	\b, %u type
+# plural s 
+>>(4.L+28)	beshort+1	>1	\bs
+# resource type list array; 1st resource type like: ALRT CODE FOND MPSR icns scsz
+>>(4.L+30)	ubelong		x	\b, %#x
+>>(4.L+30)	string		x	'%-.4s'
+# resourceCount; number of this type resources minus one. If there is one resource of this type, this is 0x0000
+>>(4.L+34)	beshort+1	x	* %d
+# resourceListOffset; offset from type list to resource list like: Ah 12h DAh
+>(4.L+36)	ubeshort	x	resource offset %#x
 
 #https://en.wikipedia.org/wiki/AppleScript
 0	string	FasdUAS			AppleScript compiled
--- a/magic/Magdir/archive
+++ b/magic/Magdir/archive
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: archive,v 1.169 2022/09/12 13:13:28 christos Exp $
+# $File: archive,v 1.179 2022/12/21 15:50:59 christos Exp $
 # archive:  file(1) magic for archive formats (see also "msdos" for self-
 #           extracting compressed archives)
 #
@@ -506,11 +506,12 @@
 >>>>0	use	ttcomp
 0	string	\1\4
 # TODO:
-# skip Commodore PET BASIC 4.0 program *.prg
-# variant ASCII, 1K dictionary (strength=48=50-2). With strength=49 wrong order! WHY?
 # skip shared library (strength=50) handled by ./ibm6000
 !:strength	-2
->0	use	ttcomp
+# skip Commodore PET BASIC programs (Mastermind.prg) with last 3 nil bytes (\0~end of line followed by 0000h line offset)
+#>-4	ubelong		x	LAST_BYTES=%8.8x
+>-4	ubelong&0x00FFffFF	!0
+>>0	use	ttcomp
 #	display information of TTComp archive
 0	name	ttcomp
 # (version 5.25) labeled the entry as "TTComp archive data"
@@ -753,6 +754,88 @@
 !:ext	??$
 >>8	ulelong	>0		\b, original size: %u bytes
 
+# Summary:	lzss compressed/EDI Pack
+# From:		Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/EDI_Install_packed_file
+# Note:		called "EDI Install LZS compressed data" by TrID and verified by
+#		command like `deark -l -m edi_pack -d2 BOOK01A.IC$` as "EDI Pack LZSS1"
+0	string					EDILZSS
+>7	string					1
+# look for point character before orginal file name extension
+>>8	search/9/b				.
+# check suffix of possible orginal file anme
+#>>>&0		ubelong				x	SUFFIX=%8.8x
+# samples without valid character after point in original file name field like: FENNEL.LZS PLANTAIN.LZS
+>>>&0		ubyte				<0x20
+>>>>0			use				edi-lzs
+# samples with valid character after point in original file name field
+>>>&0		ubyte				>0x1F
+# check 2nd charcter of suffix
+#>>>>&0			ubyte	x			2ND_SUFFIX=%x
+# sample with one valid character after point followed by \0 in original file name field like: SPELMATE.H$
+>>>>&0			ubyte			=0
+>>>>>0				use			edi-pack
+>>>>&0			ubyte			>0x1F
+# check 3rd charcter of suffix
+#>>>>>&0				ubyte		x	3RD_SUFFIX=%x
+# no sample with 2 valid characters after point followed by \0 in original file name field
+>>>>>&0				ubyte		=0
+>>>>>>0					use		edi-pack
+# samples with valid 3rd character after point in original file name field
+>>>>>&0				ubyte		>0x1F
+# sample with 3 valid character after point followed by \0 in original file name field like: BOOK01A.IC$ CTL3D.DL$
+>>>>>>&0				ubyte	=0
+>>>>>>>0					use	edi-pack
+# sample with 3 valid character after point followed by no \0 in original file name field like: HERBTEXT.LZS
+>>>>>>&0				ubyte	!0
+>>>>>>>0					use	edi-lzs
+# no sample with invalid 3rd character after point in original file name field
+>>>>>&0				default		x
+>>>>>>0					use		edi-lzs
+# sample with invalid 2nd character after point in original file name field like: LACERATE.LZS SPLINTER.LZS
+>>>>&0			default			x
+>>>>>0	use						edi-lzs
+# sample without point character in original file name field like GUNSHOT.LZS
+>>8	default					x
+>>>0		use					edi-lzs
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/e/edi-lzss2.trid.xml
+# Note:		called "EDI Install Pro LZSS2 compressed data" by TrID and verified by
+#		command like `deark -l -m edi_pack -d2 4WAY.WA$` as "EDI Pack LZSS2"
+>7	string			2			EDI LZSS2 packed
+#!:mime	application/octet-stream
+!:mime	application/x-edi-pack-lzss
+# the name of a compressed file often ends in character '$' or '_'
+!:ext	??$/??_
+# original filename, NUL-terminated, padded to 13 bytes like: mci.vbx 4way.wav skymap.exe cmdialog.vbx
+>>8		string		x			"%-0.13s"
+# original file size, as a 4-byte integer.
+>>21		ulelong		x			\b, %u bytes
+# compressed data like: ff5249464606ec00 ff4d5aa601010000
+>>>25		ubequad		x			\b, data %#16.16llx...
+0	name		edi-pack
+# Note:		verified by command like `deark -l -d2 SPELMATE.H$` as "EDI Pack LZSS1"
+# original filename, NUL-terminated, padded to 13 bytes like: ctl3d.dll spelmate.h filemenu.rc owl.def index-it.exe
+# but not like \377Aloe.lzs\273 (HERBTEXT.LZS)
+>8	string		x				EDI LZSS packed "%-.13s"
+#!:mime	application/octet-stream
+!:mime	application/x-edi-pack-lzss
+# the name of a compressed file often ends in character '$' or '_'
+!:ext	??$/?$
+# compressed data like: f7000001eff02020 ff4d5aa900020000 ff2f2a207370656c
+>21	ubequad		x				\b, data %#16.16llx...
+# URL:		http://fileformats.archiveteam.org/wiki/EDI_LZSSLib
+# Note:		verified partly by command like `deark -l -m edi_pack -d2 GUNSHOT.LZS` as "EDI LZSSLib"
+0	name		edi-lzs
+# Note:		verified by command like `deark -l -d2 GUNSHOT.LZS` as "EDI LZSSLib"
+# no original filename looks like: \277BM\226.\0 \277BM.n\001 \277BM\226.\0 \277BM.g\001 \377Aloe.lzs\273
+>8	string		x				EDI LZSSLib packed
+#!:mime	application/octet-stream
+!:mime	application/x-edi-pack-lzss
+# The name of a compressed file ends with LZS suffix
+!:ext	lzs
+# compressed data like: bf424df6e10100f3 ff416c6f652e6c7a ff416c6f652e6c7a
+>8	ubequad		x				\b, data %#16.16llx...
+
 # Summary:	CAZIP compressed file
 # From:		Joerg Jenderek
 # URL:		http://fileformats.archiveteam.org/wiki/CAZIP
@@ -791,8 +874,6 @@
 3	string	OctSqu Squash archive data
 # Terse
 0	string	\5\1\1\0 Terse archive data
-# PUCrunch
-0	string	\x01\x08\x0b\x08\xef\x00\x9e\x32\x30\x36\x31 PUCrunch archive data
 # UHarc
 0	string	UHA UHarc archive data
 # ABComp
@@ -821,8 +902,10 @@
 # QFC
 0	string	\x1aFC\x1a QFC archive data
 0	string	\x1aQF\x1a QFC archive data
-# PRO-PACK
-0	string	RNC PRO-PACK archive data
+# PRO-PACK https://www.segaretro.org/Rob_Northen_compression
+0	string	RNC
+>3	byte	1	PRO-PACK archive data (compression 1)
+>3	byte	2	PRO-PACK archive data (compression 2)
 # 777
 0	string	777 777 archive data
 # LZS221
@@ -1234,7 +1317,7 @@
 >>>>>>3	regex		\^lh[01]	LHarc 1.x/ARX archive data
 # LHice archiver use ".ICE" as name extension instead usual one ".lzh"
 # FOOBAR archiver use ".foo" as name extension instead usual one
-# "Florain Orjanov's and Olga Bachetska's ARchiver" not found at the moment
+# "Florian Orjanov's and Olga Bachetska's ARchiver" not found at the moment
 >>>>>>>2	string	-lh1		\b 
 !:ext lha/lzh/ice
 >>>>>>3	regex		\^lh[23d]	LHa 2.x? archive data
@@ -1789,6 +1872,14 @@
 !:mime	application/zip
 !:ext zip/cbz
 
+# Recognize ZIP archives with prepended data by end-of-central-directory record
+# https://en.wikipedia.org/wiki/ZIP_(file_format)#End_of_central_directory_record_(EOCD)
+# by Michal Gorny <mgorny@gentoo.org>
+-2	uleshort	0
+>&-22	string	PK\005\006	Zip archive, with extra data prepended
+!:mime	application/zip
+!:ext zip/cbz
+
 # ACE archive (from http://www.wotsit.org/download.asp?f=ace)
 # by Stefan `Sec` Zehl <sec@42.org>
 7	string		**ACE**		ACE archive data
@@ -2066,6 +2157,7 @@
 # https://gitweb.gentoo.org/proj/portage.git/tree/man/xpak.5
 -4	string	STOP
 >-16	string	XPAKSTOP	Gentoo binary package (XPAK)
+!:mime	application/vnd.gentoo.xpak
 
 # From:		Joerg Jenderek
 # URL:		https://kodi.wiki/view/TexturePacker
@@ -2110,3 +2202,71 @@
 
 # From wof (wof@stachelkaktus.net)
 0	string	Unison\ archive\ format	Unison archive format
+
+# https://ankiweb.net
+30	string	collection.anki2	Anki APKG file
+#!:ext	.apkg
+
+# Synology archive (DiskStation Manager 7.0+)
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# Note: These archives are signed and encrypted.
+0		ulelong&0xFFFFFF00	0xEFBEAD00
+# MessagePack header (fixarray of 5 elements starting with a bin of 32 bytes)
+>8  	ulelong&0x00FFFFFF	0x20C495	Synology archive
+!:ext	spk
+# Extract some properties from MessagePack third item
+>>43	search/0x10000		package=
+>>>&0	string				x			\b, package %s
+>>43	search/0x10000		arch=
+>>>&0	string				x			%s
+>>43	search/0x10000		version=
+>>>&0	string				x			%s
+>>43	search/0x10000		create_time=
+>>>&0	string				x			\b, created on %s
+
+# MonoGame/XNA processed assets archive
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/MonoGame/MonoGame/blob/v3.8.1/MonoGame.Framework/Content/ContentManager.cs
+0	string	XNB
+# XNB must be version 4 or 5
+>4	byte	<6
+>>4	byte	>3
+# Size must be positive
+>>>6	lelong	>0	MonoGame/XNA processed assets
+!:ext	xnb
+>>>>3	string	=w	\b, for Windows
+>>>>3	string	=x	\b, for Xbox360
+>>>>3	string	=i	\b, for iOS
+>>>>3	string	=a	\b, for Android
+>>>>3	string	=d	\b, for DesktopGL
+>>>>3	string	=X	\b, for MacOSX
+>>>>3	string	=W	\b, for WindowsStoreApp
+>>>>3	string	=n	\b, for NativeClient
+>>>>3	string	=M	\b, for WindowsPhone8
+>>>>3	string	=r	\b, for RaspberryPi
+>>>>3	string	=P	\b, for PlayStation4
+>>>>3	string	=5	\b, for PlayStation5
+>>>>3	string	=O	\b, for XboxOne
+>>>>3	string	=S	\b, for Nintendo Switch
+>>>>3	string	=G	\b, for Google Stadia
+>>>>3	string	=b	\b, for WebAssembly and Bridge.NET
+>>>>3	string	=m	\b, for WindowsPhone7.0 (XNA)
+>>>>3	string	=p	\b, for PlayStationMobile
+>>>>3	string	=v	\b, for PSVita
+>>>>3	string	=g	\b, for Windows (OpenGL)
+>>>>3	string	=l	\b, for Linux
+>>>>4	byte	x	\b, version %d
+>>>>5	byte	&0x80	\b, LZX compressed
+>>>>>10	lelong	x	\b, decompressed size: %d bytes
+>>>>5	byte	&0x40	\b, LZ4 compressed
+>>>>>10	lelong	x	\b, decompressed size: %d bytes
+
+# Electron ASAR archive
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/electron/asar
+0		ulelong	4
+# Match JSON header start and end
+>16		string	{"files":{"
+>>(12.l+12)	string }}}}		Electron ASAR archive
+!:ext	asar
+>>>12		ulelong	x		\b, header length: %d bytes
--- a/magic/Magdir/arm
+++ b/magic/Magdir/arm
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: arm,v 1.2 2021/07/14 17:40:31 christos Exp $
+# $File: arm,v 1.3 2022/10/31 14:35:39 christos Exp $
 # arm: file(1) magic for ARM COFF
 #
 # https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
@@ -36,6 +36,15 @@
 # test for unused flag bits in f_flags
 >18	uleshort&0x8E80	0
 # use little endian variant of subroutine to
+# display name+variables+flags for common object formatted files
+>>0	use				display-coff
+!:strength -10
+
+# ARM64EC
+0	leshort		0xa641
+# test for unused flag bits in f_flags
+>18	uleshort&0x8E80	0
+# use little endian variant of subroutine to
 # display name+variables+flags for common object formatted files
 >>0	use				display-coff
 !:strength -10
--- a/magic/Magdir/asf
+++ b/magic/Magdir/asf
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: asf,v 1.3 2022/04/25 17:33:13 christos Exp $
+# $File: asf,v 1.4 2022/10/31 13:22:26 christos Exp $
 # asf:  file(1) magic for Microsoft Advanced Systems Format (ASF) files
 # http://www.staroceans.org/e-book/ASF_Specification.pdf
 
@@ -21,7 +21,7 @@
 # ASF_Stream_Properties_Object
 >0	guid	B7DC0791-A9B7-11CF-8EE6-00C00C205365
 #>>56	lequad	x		Time Offset %lld
-#>>64	lelong	x		Type-Specicic Data Length %d
+#>>64	lelong	x		Type-Specific Data Length %d
 #>>68	lelong	x		Error Correction Data Length %d
 #>>72	leshort	x		Flags %#x
 #>>74	lelong	x		Reserved %x
--- a/magic/Magdir/audio
+++ b/magic/Magdir/audio
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: audio,v 1.124 2022/08/28 08:58:20 christos Exp $
+# $File: audio,v 1.126 2022/10/09 13:40:22 christos Exp $
 # audio:  file(1) magic for sound formats (see also "iff")
 #
 # Jan Nicolai Langfeldt (janl@ifi.uio.no), Dan Quinlan (quinlan@yggdrasil.com),
--- a/magic/Magdir/blender
+++ b/magic/Magdir/blender
@@ -1,13 +1,24 @@
 
 #------------------------------------------------------------------------------
-# $File: blender,v 1.8 2019/04/19 00:42:27 christos Exp $
+# $File: blender,v 1.9 2022/12/21 15:53:27 christos Exp $
 # blender: file(1) magic for Blender 3D related files
 #
 # Native format rule v1.2. For questions use the developers list
 # https://lists.blender.org/mailman/listinfo/bf-committers
 # GLOB chunk was moved near start and provides subversion info since 2.42
-
+# Update:	Joerg Jenderek
+# URL: 		http://fileformats.archiveteam.org/wiki/BLEND
+#		http://www.blender.org/
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/b/blend.trid.xml
+#		http://formats.kaitai.io/blender_blend/index.html
+# Note:		called "Blender 3D data" by TrID
+#		and gzip compressed variant handled by ./compress
 0		string	=BLENDER	Blender3D,
+#!:mime		application/octet-stream
+!:mime		application/x-blender
+!:ext		blend
+# no sample found with extension blender
+#!:ext		blend/blender
 >7		string	=_		saved as 32-bits
 >>8		string	=v		little endian
 >>>9		byte	x		with version %c.
--- a/magic/Magdir/c-lang
+++ b/magic/Magdir/c-lang
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: c-lang,v 1.30 2021/08/16 10:17:05 christos Exp $
+# $File: c-lang,v 1.31 2022/12/01 22:04:33 christos Exp $
 # c-lang:  file(1) magic for C and related languages programs
 #
 # The strength is to beat standard HTML
@@ -88,13 +88,13 @@
 !:strength + 30
 !:mime	text/x-c++
 0	search/8192	protected
->0	regex	\^[[:space:]]*protected:		C++ source text
+>0	regex	\^[[:space:]]*protected:	C++ source text
 !:strength + 30
 !:mime	text/x-c++
 
 # Objective-C
 0	search/8192	#import
->0	regex	\^#import			Objective-C source text
+>0	regex	\^#import[[:space:]]+["<]	Objective-C source text
 !:strength + 25
 !:mime	text/x-objective-c
 
--- a/magic/Magdir/c64
+++ b/magic/Magdir/c64
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: c64,v 1.12 2022/05/14 20:03:39 christos Exp $
+# $File: c64,v 1.13 2022/11/21 22:25:37 christos Exp $
 # c64:  file(1) magic for various commodore 64 related files
 #
 # From: Dirk Jagdmann <doj@cubic.org>
@@ -194,7 +194,338 @@
 >100	byte		>0		\b, %u subsong(s)
 
 # CBM BASIC (cc65 compiled)
+# Summary:	binary executable or Basic program for Commodore C64 computers
+# Update:	Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/Commodore_BASIC_tokenized_file
+# Reference:	https://www.c64-wiki.com/wiki/BASIC_token
+#		https://github.com/thezerobit/bastext/blob/master/bastext.doc
+#		http://mark0.net/download/triddefs_xml.7z/defs/p/prg-c64.trid.xml
+# TODO:		unify Commodore BASIC/program sub routines
+# Note:		"PUCrunch archive data" moved from ./archive and merged with c64-exe
 0	leshort		0x0801
->2	leshort		0x080b
->6	string		\x9e		CBM BASIC
->7	string		>\0		\b, SYS %s
+# if first token is not SYS this implies BASIC program in most cases
+>6		ubyte		!0x9e
+# but sELF-ExTRACTING-zIP executable unzp6420.prg contains SYS token at end of second BASIC line (at 0x35)
+>>23		search/30	\323ELF-E\330TRACTING-\332IP
+>>>0		use		c64-exe
+>>23		default		x
+>>>0		use		c64-prg
+# if first token is SYS this implies binary executable
+>6		ubyte		=0x9e
+>>0		use		c64-exe
+# display information about C64 binary executable (memory address, line number, token)
+0	name	c64-exe
+>0		uleshort	x	Commodore C64
+# http://a1bert.kapsi.fi/Dev/pucrunch/
+# start address 0801h; next offset 080bh; BASIC line number is 239=00EFh; BASIC instruction is SYS 2061
+# the above combination appartly also occur for other Commodore programs like: gunzip111.c64.prg
+# and there exist PUCrunch archive for other machines like C16 with other magics
+>0		string	\x01\x08\x0b\x08\xef\x00\x9e\x32\x30\x36\x31	program, probably PUCrunch archive data
+!:mime	application/x-compress-pucrunch
+!:ext	prg/pck
+>0		string	!\x01\x08\x0b\x08\xef\x00\x9e\x32\x30\x36\x31	program
+!:mime	application/x-commodore-exec
+!:ext	prg/
+# start address like: 801h
+>0		uleshort	!0x0801	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x800)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# valid 2nd BASIC fragment found only in sELF-ExTRACTING-zIP executable unzp6420.prg
+>>23		search/30	\323ELF-E\330TRACTING-\332IP
+# jump again from beginning
+>>>(2.s-0x800)	ubyte		x
+>>>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about tokenized C64 BASIC program (memory address, line number, token)
+0	name	c64-prg
+>0		uleshort	x	Commodore C64 BASIC program
+!:mime	application/x-commodore-basic
+# Tokenized BASIC programs were stored by Commodore as file type program "PRG" in separate field in directory structures.
+# So file name can have no suffix like in saveroms; When transferring to other platforms, they are often saved with .prg extensions.
+# BAS suffix is typically used for the BASIC source but also found in program pods.bas
+!:ext	prg/bas/
+# start address like: 801h
+>0		uleshort	!0x0801	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x0800)	ubyte		x	
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# 2nd BASIC fragment
+>>&0		use		basic-line
+# zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# Summary:	binary executable or Basic program for Commodore C128 computers
+# URL:		https://en.wikipedia.org/wiki/Commodore_128
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/p/prg-c128.trid.xml
+# From:		Joerg Jenderek
+# Note:		Commodore 128 BASIC 7.0 variant; there exist varaints with different start addresses
+0		leshort		0x1C01
+!:strength	+1
+# GRR: line above with strength 51 (50+1) is too generic because it matches SVr3 curses screen image, big-endian with strength (50) handled by ./terminfo
+# probably skip SVr3 curses images with "invalid high" second line offset 
+>2		uleshort	<0x1D02
+# skip foo with "invalid low" second line offset
+>>2		uleshort	>0x1C06
+# if first token is not SYS this implies BASIC program
+>>>6		ubyte		!0x9e
+>>>>0			use	c128-prg
+# if first token is SYS this implies binary executable
+>>>6		ubyte		=0x9e
+>>>>0		use		c128-exe
+# Summary:	binary executable or Basic program for Commodore C128 computers
+# Note:		Commodore 128 BASIC 7.1 extension by Rick Simon
+# start adress 132Dh
+#0		leshort		0x132D	THIS_IS_C128_7.1
+#>0			use	c128-prg
+# Summary:	binary executable or Basic program for Commodore C128 computers
+# Note:		Commodore 128 BASIC 7.0 saved with graphics mode enabled
+# start adress 4001h
+#0		leshort		0x4001	THIS_IS_C128_GRAPHIC
+#>0			use	c128-prg
+# display information about tokenized C128 BASIC program (memory address, line number, token)
+0	name	c128-prg
+>0		uleshort	x	Commodore C128 BASIC program
+!:mime	application/x-commodore-basic
+!:ext	prg
+# start address like: 1C01h
+>0		uleshort	!0x1C01	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x1C00)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# 2nd BASIC fragment
+>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about C128 program (memory address, line number, token)
+0	name	c128-exe
+>0		uleshort	x	Commodore C128 program
+!:mime	application/x-commodore-exec
+!:ext	prg/
+# start address like: 1C01h
+>0		uleshort	!0x1C01	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x1C00)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# no valid 2nd BASIC fragment in Commodore executables
+#>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# Summary:	binary executable or Basic program for Commodore C16/VIC-20/Plus4 computers
+# URL:		https://en.wikipedia.org/wiki/Commodore_Plus/4
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/p/prg-vic20.trid.xml
+#		defs/p/prg-plus4.trid.xml
+# From:		Joerg Jenderek
+# Note:		there exist VIC-20 variants with different start address
+# GRR: line below is too generic because it matches Novell LANalyzer capture
+# with regular trace header record handled by ./sniffer
+0		leshort		0x1001
+# skip regular Novell LANalyzer capture (novell-2.tr1 novell-lanalyzer.tr1 novell-win10.tr1) with "invalid low" token value 54h
+>6		ubyte		>0x7F
+# skip regular Novell LANalyzer capture (novell-2.tr1 novell-lanalyzer.tr1 novell-win10.tr1) with "invalid low" second line offset 4Ch
+#>>2		uleshort	>0x1006	OFFSET_NOT_TOO_LOW
+# skip foo with "invalid high" second line offset but not for 0x123b (Minefield.prg)
+#>>>2		uleshort	<0x1102	OFFSET_NOT_TOO_HIGH
+# if first token is not SYS this implies BASIC program
+>>6		ubyte		!0x9e
+# valid second end of line separator implies BASIC program
+>>>(2.s-0x1000)		ubyte	=0
+>>>>0			use	c16-prg
+# invalid second end of line separator !=0 implies binary executable like: Minefield.prg
+>>>(2.s-0x1000)		ubyte	!0
+>>>>0			use	c16-exe
+# if first token is SYS this implies binary executable
+>>6		ubyte		=0x9e
+>>>0		use		c16-exe
+# display information about C16 program (memory address, line number, token)
+0	name	c16-exe
+>0		uleshort	x	Commodore C16/VIC-20/Plus4 program
+!:mime	application/x-commodore-exec
+!:ext	prg/
+# start address like: 1001h
+>0		uleshort	!0x1001	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x1000)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# no valid 2nd BASIC fragment in excutables
+#>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about tokenized C16 BASIC program (memory address, line number, token)
+0	name	c16-prg
+>0		uleshort	x	Commodore C16/VIC-20/Plus4 BASIC program
+!:mime	application/x-commodore-basic
+!:ext	prg
+# start address like: 1001h
+>0		uleshort	!0x1001	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x1000)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# 2nd BASIC fragment
+>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# Summary:	binary executable or Basic program for Commodore VIC-20 computer with 8K RAM expansion
+# URL:		https://en.wikipedia.org/wiki/VIC-20
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/p/prg-vic20-8k.trid.xml
+# From:		Joerg Jenderek
+# Note:		Basic v2.0 with Basic v4.0 extension (VIC20); there exist VIC-20 variants with different start addresses
+# start adress 1201h
+0		leshort		0x1201
+# if first token is not SYS this implies BASIC program
+>6		ubyte		!0x9e
+>>0		use		vic-prg
+# if first token is SYS this implies binary executable
+>6		ubyte		=0x9e
+>>0		use		vic-exe
+# display information about Commodore VIC-20 BASIC+8K program (memory address, line number, token)
+0	name	vic-prg
+>0		uleshort	x	Commodore VIC-20 +8K BASIC program
+!:mime	application/x-commodore-basic
+!:ext	prg
+# start address like: 1201h
+>0		uleshort	!0x1201	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x1200)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# 2nd BASIC fragment
+>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about Commodore VIC-20 +8K program (memory address, line number, token)
+0	name	vic-exe
+>0		uleshort	x	Commodore VIC-20 +8K program
+!:mime	application/x-commodore-exec
+!:ext	prg/
+# start address like: 1201h
+>0		uleshort	!0x1201	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x0400)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# no valid 2nd BASIC fragment in excutables
+#>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# Summary:	binary executable or Basic program for Commodore PET computers
+# URL:		https://en.wikipedia.org/wiki/Commodore_PET
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/p/prg-pet.trid.xml
+# From:		Joerg Jenderek
+# start adress 0401h
+0		leshort		0x0401
+!:strength	+1
+# GRR: line above with strength 51 (50+1) is too generic because it matches TTComp archive data, ASCII, 1K dictionary
+# (strength=48=50-2) handled by ./archive and shared library (strength=50) handled by ./ibm6000
+# skip TTComp archive data, ASCII, 1K dictionary ttcomp-ascii-1k.bin with "invalid high" second line offset 4162h
+>2		uleshort	<0x0502
+# skip foo with "invalid low" second line offset
+#>>2		uleshort	>0x0406	OFFSET_NOT_TOO_LOW
+# skip bar with "invalid end of line" 
+#>>>(2.s-0x0400)	ubyte		=0	END_OF_LINE_OK
+# if first token is not SYS this implies BASIC program
+>>6		ubyte		!0x9e
+>>>0		use		pet-prg
+# if first token is SYS this implies binary executable
+>>6		ubyte		=0x9e
+>>>0		use		pet-exe
+# display information about Commodore PET BASIC program (memory address, line number, token)
+0	name	pet-prg
+>0		uleshort	x	Commodore PET BASIC program
+!:mime	application/x-commodore-basic
+!:ext	prg
+# start address like: 0401h
+>0		uleshort	!0x0401	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x0400)	ubyte		x
+# 2nd BASIC fragment
+>>&0		use		basic-line
+# zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about Commodore PET program (memory address, line number, token)
+0	name	pet-exe
+>0		uleshort	x	Commodore PET program
+!:mime	application/x-commodore-exec
+!:ext	prg/
+# start address like: 0401h
+>0		uleshort	!0x0401	\b, start address %#4.4x
+# 1st BASIC fragment
+>2		use		basic-line
+# jump to 1 byte before next BASIC fragment; this must be zero-byte marking the end of line
+>(2.s-0x0400)	ubyte		x
+>>&-1		ubyte		!0	\b, no EOL=%#x
+# no valid 2nd BASIC fragment in excutables
+#>>&0		use		basic-line
+# Zero-byte marking the end of the BASIC line
+>-3		ubyte		!0	\b, 3 last bytes %#2.2x
+# Two zero-bytes in place of the pointer to next BASIC line indicates the end of the program
+>>-2		ubeshort	x	\b%4.4x
+# display information about tokenized BASIC line (memory address, line number, Token)
+0	name	basic-line
+# pointer to memory address of beginning of "next" BASIC line
+# greater then previous offset but maximal 100h difference
+>0		uleshort	x	\b, offset %#4.4x
+# BASIC line number with range from 0 to 65520; practice to increment numbers by some value (5, 10 or 100)
+>2		uleshort	x	\b, line %u
+# https://www.c64-wiki.com/wiki/BASIC_token
+# The "high-bit" bytes from #128-#254 stood for the various BASIC commands and mathematical operators
+>4		ubyte		x	\b, token (%#x)
+# https://www.c64-wiki.com/wiki/REM
+>4		string		\x8f	REM
+# remark string like: ** SYNTHESIZER BY RICOCHET **
+>>5		string		>\0	%s
+#>>>&1		uleshort	x	\b, NEXT OFFSET %#4.4x
+# https://www.c64-wiki.com/wiki/PRINT
+>4		string		\x99	PRINT
+# string like: "Hello world" "\021 \323ELF-E\330TRACTING-\332IP (64 ONLY)\016\231":\2362141
+>>5		string		x	%s
+#>>>&0		ubequad		x	AFTER_PRINT=%#16.16llx
+# https://www.c64-wiki.com/wiki/POKE
+>4		string		\x97	POKE
+# <Memory address>,<number>
+>>5		regex		\^[0-9,\040]+	%s
+# https://www.c64-wiki.com/wiki/SYS	0x9e=\236
+>4		string		\x9e	SYS
+# SYS <Address> parameter is a 16-bit unsigned integer; in the range 0 - 65535
+>>5		regex		\^[0-9]{1,5}	%s
+# maybe followed by spaces, "control-characters" or colon (:) followed by next commnds or in victracker.prg
+# (\302(43)\252256\254\302(44)\25236) /T.L.R/
+#>>5		string		x	SYS_STRING="%s"
+# https://www.c64-wiki.com/wiki/GOSUB
+>4		string		\x8d	GOSUB
+# <line>
+>>5		string		>\0	%s
--- a/magic/Magdir/cad
+++ b/magic/Magdir/cad
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: cad,v 1.29 2021/12/06 19:33:27 christos Exp $
+# $File: cad,v 1.31 2022/12/09 15:36:23 christos Exp $
 # autocad:  file(1) magic for cad files
 #
 
@@ -301,18 +301,50 @@
 # https://docs.techsoft3d.com/visualize/3df/latest/build/general/hsf/\
 # HSF_architecture.html
 # Stephane Charette <stephane.charette@gmail.com>
-0	string	;;\020HSF\020V		OpenHSF (Hoops Stream Format)
->7	regex/9 V[.0-9]{4,5}\020	%s
+0	string	;;\040HSF\040V		OpenHSF (Hoops Stream Format)
+>7	regex/9 V[.0-9]{4,5}\040	%s
 !:ext hsf
 
 # AutoCAD Drawing Exchange Format
+# Update:	Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/DXF
+#		https://en.wikipedia.org/wiki/AutoCAD_DXF
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/d/
+#		dxf-var0.trid.xml dxf-var0u.trid.xml dxf-var2.trid.xml dxf-var2u.trid.xml
+# Note:		called "AutoCAD Drawing eXchange Format" by TrID and
+#		"Drawing Interchange File Format (ASCII)" by DROID
+# GRR: some samples does not match 1st test like: abydos.dxf
 0	regex		\^[\ \t]*0\r?\000$
 >1	regex		\^[\ \t]*SECTION\r?$
 >>2	regex		\^[\ \t]*2\r?$
+# GRR: some samples without HEADER section like: airplan2.dxf
 >>>3	regex		\^[\ \t]*HEADER\r?$	AutoCAD Drawing Exchange Format
-!:mime	application/x-dxf
+#!:mime	application/x-dxf
+!:mime	image/vnd.dxf
 !:ext	dxf
+# DROID PUID fmt/64	fmt-64-signature-id-99.dxf
+>>>>&1	search/8192	MC0.0			\b, 1.0
+# DROID PUID fmt/65	fmt-65-signature-id-100.dxf
+>>>>&1	search/8192	AC1.2			\b, 1.2
+# DROID PUID fmt/66	fmt-66-signature-id-101.dxf
+>>>>&1	search/8192	AC1.3			\b, 1.3
+# DROID PUID fmt/67	fmt-67-signature-id-102.dxf
+>>>>&1	search/8192	AC1.40			\b, 1.4
+# DROID PUID fmt/68	fmt-68-signature-id-103.dxf
+>>>>&1	search/8192	AC1.50			\b, 2.0
+# DROID PUID fmt/69	fmt-69-signature-id-104.dxf
+>>>>&1	search/8192	AC2.10			\b, 2.1
+# DROID PUID fmt/70	fmt-70-signature-id-105.dxf
+>>>>&1	search/8192	AC2.21			\b, 2.2
+# DROID PUID fmt/71	fmt-71-signature-id-106.dxf
+>>>>&1	search/8192	AC1002			\b, 2.5
+# DROID PUID fmt/72	fmt-72-signature-id-107.dxf
+>>>>&1	search/8192	AC1003			\b, 2.6
+# DROID PUID fmt/73	fmt-73-signature-id-108.dxf
+>>>>&1	search/8192	AC1004			\b, R9
 >>>>&1	search/8192	AC1006			\b, R10
+# http://cd.textfiles.com/amigaenv/DXF/OBJEKTE/LASTMINUTE/apple.dxf
+#>>>>&1	search/8192	AC1008			\b, Rfoo
 >>>>&1	search/8192	AC1009			\b, R11/R12
 >>>>&1	search/8192	AC1012			\b, R13
 >>>>&1	search/8192	AC1013			\b, R13c3
--- a/magic/Magdir/coff
+++ b/magic/Magdir/coff
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: coff,v 1.6 2021/04/26 15:56:00 christos Exp $
+# $File: coff,v 1.7 2022/11/21 22:30:22 christos Exp $
 # coff: file(1) magic for Common Object Files not specific to known cpu types or manufactures
 #
 # COFF
@@ -37,6 +37,7 @@
 # ARM COFF (./arm)
 >>>>0	uleshort	0xaa64		Aarch64
 >>>>0	uleshort	0x01c0		ARM
+>>>>0	uleshort	0xa641		ARM64EC
 >>>>0	uleshort	0x01c2		ARM Thumb
 >>>>0	uleshort	0x01c4		ARMv7 Thumb
 # TODO for other COFFs
--- a/magic/Magdir/commands
+++ b/magic/Magdir/commands
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: commands,v 1.69 2022/04/20 21:14:23 christos Exp $
+# $File: commands,v 1.73 2022/11/06 18:39:23 christos Exp $
 # commands:  file(1) magic for various shells and interpreters
 #
 #0	string/w	:			shell archive or script for antique kernel text
@@ -8,6 +8,8 @@
 !:mime	text/x-shellscript
 0	string/fwb	#!\ /bin/sh		POSIX shell script executable (binary data)
 !:mime	text/x-shellscript
+>10	string	#\040This\040script\040was\040generated\040using\040Makeself	\b, self-executable archive
+>>53	string	x	\b, Makeself %s
 
 0	string/fwt	#!\ /bin/csh		C shell script text executable
 !:mime	text/x-shellscript
@@ -97,9 +99,6 @@
 0	string/fwt	#!\ /usr/bin/env\ fish		fish shell script text executable
 !:mime	text/x-shellscript
 
-0	string/wt	#!\ 	a
->&-1	string/T	x	%s script text executable
-
 0	search/1/fwt	#!\ /usr/bin/tclsh	Tcl/Tk script text executable
 !:mime  text/x-tcl
 
@@ -189,3 +188,14 @@
 # From Danny Weldon
 0	string	\x0b\x13\x08\x00
 >0x04   uleshort	<4      ksh byte-code version %d
+
+# From: arno <arenevier@fdn.fr>
+# mozilla xpconnect typelib
+# see https://www.mozilla.org/scriptable/typelib_file.html
+0	string 		XPCOM\nTypeLib\r\n\032		XPConnect Typelib
+>0x10  byte        x       version %d
+>>0x11 byte        x      \b.%d
+
+0	string/fwt	#!\ /usr/bin/env\ runghc	GHC script executable
+0	string/fwt	#!\ /usr/bin/env\ runhaskell	Haskell script executable
+0	string/fwt	#!\ /usr/bin/env\ julia	Julia script executable
--- a/magic/Magdir/compress
+++ b/magic/Magdir/compress
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: compress,v 1.83 2022/08/16 11:16:39 christos Exp $
+# $File: compress,v 1.88 2022/12/21 15:55:52 christos Exp $
 # compress:  file(1) magic for pure-compression formats (no archives)
 #
 # compress, gzip, pack, compact, huf, squeeze, crunch, freeze, yabba, etc.
@@ -12,13 +12,14 @@
 0	string		\037\235	compress'd data
 !:mime	application/x-compress
 !:apple	LZIVZIVU
+!:ext	Z
 >2	byte&0x80	>0		block compressed
 >2	byte&0x1f	x		%d bits
 
 # gzip (GNU zip, not to be confused with Info-ZIP or PKWARE zip archiver)
 # URL: https://en.wikipedia.org/wiki/Gzip
 # Reference: https://tools.ietf.org/html/rfc1952
-# Update: Joerg Jenderek, Apr 2019
+# Update: Joerg Jenderek, Apr 2019, Dec 2022
 #   Edited by Chris Chittleborough <cchittleborough@yahoo.com.au>, March 2002
 #	* Original filename is only at offset 10 if "extra field" absent
 #	* Produce shorter output - notably, only report compression methods
@@ -61,20 +62,24 @@
 !:mime	application/gzip
 >>>0	use	gzip-info
 # size of the original (uncompressed) input data modulo 2^32
->>-0	offset		>48
+# TODO: check for GXD MCD cad the reported size
 >>>-4	ulelong		x		\b, original size modulo 2^32 %u
->>-0	offset		<48		\b, truncated
 # gzipped TAR or VirtualBox extension package
 #!:mime	application/x-compressed-tar
 #!:mime	application/x-virtualbox-vbox-extpack
 # https://www.w3.org/TR/SVG/mimereg.html
-#!:mime	image/image/svg+xml-compressed
+#!:mime	image/svg+xml-compressed
 #	zlib.3.gz
 #	microcode-20180312.tgz
 #	tpz same as tgz
 #	lua-md5_1.2-1_i386_i486.ipk	https://en.wikipedia.org/wiki/Opkg
 #	Oracle_VM_VirtualBox_Extension_Pack-5.0.12-104815.vbox-extpack
-!:ext	gz/tgz/tpz/ipk/vbox-extpack/svgz
+#	trees.blend			http://fileformats.archiveteam.org/wiki/BLEND
+#	2020-07-19-Note-16-24.xoj	https://xournal.sourceforge.net/manual.html
+#	MYgnucash-gz.gnucash		https://wiki.gnucash.org/wiki/GnuCash_XML_format
+#	text-rotate.dia			https://en.wikipedia.org/wiki/Dia_(software)
+#	MYrdata.RData			https://en.wikipedia.org/wiki/R_(programming_language)
+!:ext	gz/tgz/tpz/ipk/vbox-extpack/svgz/blend/dia/gnucash/rdata/xoj
 # FNAME/FCOMMENT bit implies file name/comment as iso-8859-1 text
 >3	byte&0x18	>0		gzip compressed data
 !:mime	application/gzip
@@ -83,12 +88,13 @@
 #!:mime	application/x-abiword-compressed
 #!:mime	image/image/svg+xml-compressed
 #	kleopatra_splashscreen.svgz	gzipped .svg
-!:ext	gz/tgz/tpz/zabw/svgz
+#	RSI-Mega-Demo_Disk1.adz		gzipped .adf	http://fileformats.archiveteam.org/wiki/ADF_(Amiga)
+#	PostbankTest.kmy		gzipped XML	https://docs.kde.org/stable5/en/kmymoney/kmymoney/details.formats.compressed.html
+#	Logo.xcfgz			gzipped .xcf	http://fileformats.archiveteam.org/wiki/XCF
+!:ext	gz/tgz/tpz/zabw/svgz/adz/kmy/xcfgz
 >>0	use	gzip-info
 # size of the original (uncompressed) input data modulo 2^32
->>-0	offset		>48
->>>-4	ulelong		x		\b, original size modulo 2^32 %u
->>-0	offset		<48		\b, truncated
+>>-4	ulelong		x		\b, original size modulo 2^32 %u
 #	display information of gzip compressed files
 0	name				gzip-info
 #>2	byte		x		THIS iS GZIP
@@ -125,6 +131,7 @@
 # packed data, Huffman (minimum redundancy) codes on a byte-by-byte basis
 0	string		\037\036	packed data
 !:mime	application/octet-stream
+!:ext	z
 >2	belong		>1		\b, %d characters originally
 >2	belong		=1		\b, %d character originally
 #
@@ -159,6 +166,7 @@
 # lzip
 0	string		LZIP		lzip compressed data
 !:mime application/x-lzip
+!:ext lz
 >4	byte		x		\b, version: %d
 
 # squeeze and crunch
@@ -194,6 +202,7 @@
 
 # lzop from <markus.oberhumer@jk.uni-linz.ac.at>
 0	string		\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a	lzop compressed data
+!:ext	lzo
 >9	beshort		<0x0940
 >>9	byte&0xf0	=0x00		- version 0.
 >>9	beshort&0x0fff	x		\b%03x,
@@ -254,20 +263,24 @@
 !:mime	application/x-7z-compressed
 !:ext 7z/cb7
 
+0	name		lzma			LZMA compressed data,
+!:mime	application/x-lzma
+!:ext	lzma
+>5	lequad		=0xffffffffffffffff	streamed
+>5	lequad		!0xffffffffffffffff	non-streamed, size %lld
+
 # Type: LZMA
 0	lelong&0xffffff	=0x5d
->12	leshort		0xff			LZMA compressed data,
-!:mime	application/x-lzma
->>5	lequad		=0xffffffffffffffff	streamed
->>5	lequad		!0xffffffffffffffff	non-streamed, size %lld
->12	leshort		0			LZMA compressed data,
->>5	lequad		=0xffffffffffffffff	streamed
->>5	lequad		!0xffffffffffffffff	non-streamed, size %lld
+>12	leshort		0xff
+>>0	use		lzma
+>12	leshort		0
+>>0	use		lzma
 
 # http://tukaani.org/xz/xz-file-format.txt
 0	ustring		\xFD7zXZ\x00		XZ compressed data, checksum
 !:strength * 2
 !:mime	application/x-xz
+!:ext	xz
 >7	byte&0xf	0x0			NONE
 >7	byte&0xf	0x1			CRC32
 >7	byte&0xf	0x4			CRC64
@@ -283,6 +296,7 @@
 # https://fastcompression.blogspot.fi/2013/04/lz4-streaming-format-final.html
 0	lelong		0x184d2204	LZ4 compressed data (v1.4+)
 !:mime	application/x-lz4
+!:ext	lz4
 # Added by osm0sis@xda-developers.com
 0 	lelong		0x184c2103	LZ4 compressed data (v1.0-v1.3)
 !:mime	application/x-lz4
@@ -319,19 +333,26 @@
 # https://github.com/facebook/zstd/blob/dev/zstd_compression_format.md
 0     lelong       0xFD2FB522  Zstandard compressed data (v0.2)
 !:mime  application/zstd
+!:ext zst
 0     lelong       0xFD2FB523  Zstandard compressed data (v0.3)
 !:mime  application/zstd
+!:ext zst
 0     lelong       0xFD2FB524  Zstandard compressed data (v0.4)
 !:mime  application/zstd
+!:ext zst
 0     lelong       0xFD2FB525  Zstandard compressed data (v0.5)
 !:mime  application/zstd
+!:ext zst
 0     lelong       0xFD2FB526  Zstandard compressed data (v0.6)
 !:mime  application/zstd
+!:ext zst
 0     lelong       0xFD2FB527  Zstandard compressed data (v0.7)
 !:mime  application/zstd
+!:ext zst
 >4    use          zstd-dictionary-id
 0     lelong       0xFD2FB528  Zstandard compressed data (v0.8+)
 !:mime  application/zstd
+!:ext zst
 >4    use          zstd-dictionary-id
 
 # https://github.com/facebook/zstd/blob/dev/zstd_compression_format.md
@@ -407,3 +428,24 @@
 # http://www.shikadi.net/moddingwiki/PCX_Library
 0	string/b	pcxLib
 >0x0A	string/b	Copyright\020(c)\020Genus\020Microprogramming,\020Inc.	pcxLib compressed
+
+# https://support-docs.illumina.com/SW/ORA_Format_Specification/Content/SW/ORA/ORAFormatSpecification.htm
+0	uleshort	0x7c49	
+>2	lelong		0x80	ORA FASTQ compressed file
+>6	ulelong		x	\b, DNA size %u
+>10	ulelong		x	\b, read names size %u
+>14	ulelong		x	\b, quality buffer 1 size %u
+>18	ulelong		x	\b, quality buffer 2 size %u
+>22	ulelong		x	\b, sequence buffer size %u
+>26	ulelong		x	\b, N-position buffer size %u
+>30	ulelong		x	\b, crypto buffer size %u
+>34	ulelong		x	\b, misc  buffer 1 size %u
+>38	ulelong		x	\b, misc  buffer 2 size %u
+>42	ulelong		x	\b, flags %#x
+>46	lelong		x	\b, read size %d
+>50	lelong		x	\b, number of reads %d
+>54	leshort		x	\b, version %d
+
+# https://github.com/kspalaiologos/bzip3/blob/master/doc/file_format.md
+0	string/b	BZ3v1	bzip3 compressed data
+>5	ulelong		x	\b, blocksize %u
--- a/magic/Magdir/console
+++ b/magic/Magdir/console
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: console,v 1.68 2022/05/14 20:04:43 christos Exp $
+# $File: console,v 1.70 2022/10/31 13:22:26 christos Exp $
 # Console game magic
 # Toby Deshane <hac@shoelace.digivill.net>
 
@@ -68,7 +68,7 @@
 !:mime	application/x-nes-rom
 
 #------------------------------------------------------------------------------
-# fds: file(1) magic for Famciom Disk System disk images
+# fds: file(1) magic for Famicom Disk System disk images
 # Reference: https://wiki.nesdev.com/w/index.php/Family_Computer_Disk_System#.FDS_format
 # From: David Korth <gerbilsoft@gerbilsoft.com>
 # TODO: Check "Disk info block" and get info from that in addition to the optional header.
@@ -760,6 +760,28 @@
 >5	byte	0			\b, Simple Encoding
 >6	string	x			\b, description: %s
 
+# Compressed ISO disc image (used mostly by PSP, PS2 and MegaDrive)
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://en.wikipedia.org/wiki/.CSO
+# NOTE: This is NOT the same as Compact ISO or GameCube/Wii disc image,
+# though it has the same magic number.
+0               string                  CISO
+# Match CISO version 1 with ISO-9660 sector size
+>20             ubyte                   <2
+>>16            ulelong                 =2048           CSO v1 disk image
+!:mime  application/x-compressed-iso
+!:ext   ciso/cso
+>>>8            ulequad                 x               \b, original size %llu bytes
+>>>16           ulelong                 x               \b, datablock size %u bytes
+# Match CISO version 2
+>20             ubyte                   =2
+>>22            uleshort                =0
+>>>4            ulelong                 =24             CSO v2 disk image
+!:mime  application/x-compressed-iso
+!:ext   ciso/cso
+>>>>8           ulequad                 x               \b, original size %llu bytes
+>>>>16          ulelong                 x               \b, datablock size %u bytes
+
 # From: Daniel Dawson <ddawson@icehouse.net>
 # SNES9x .smv "movie" file format.
 0		string		SMV\x1A	SNES9x input recording
--- a/magic/Magdir/database
+++ b/magic/Magdir/database
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: database,v 1.67 2022/07/12 18:57:42 christos Exp $
+# $File: database,v 1.68 2022/09/23 19:54:41 christos Exp $
 # database:  file(1) magic for various databases
 #
 # extracted from header/code files by Graeme Wilford (eep2gw@ee.surrey.ac.uk)
@@ -410,8 +410,10 @@
 >>>>>>>>>>513	ubyte		>037
 # skip DOS executables CPQ0TD.DRV E30ODI.COM IBM0MONO.DRV by looking for printable 1st character of 1st memo item
 >>>>>>>>>>>512	ubyte		>037
-# unusual dBASE III DBT like adressen.dbt
->>>>>>>>>>>>0	use		dbase3-memo-print
+# skip few (14/758) Microsoft Event Trace Logs (boot_BASE+CSWITCH_1.etl DlTel-Merge.etl UpdateUx.006.etl) with invalid "high" 1st item \377\377
+>>>>>>>>>>>>512	ubyte		<0377
+# unusual dBASE III DBT like adressen.dbt biblio.dbt fsadress.dbt
+>>>>>>>>>>>>>0	use		dbase3-memo-print
 # dBASE III DBT like angest.dbt, or garbage PCX DBF
 >>>>>>>>8	ubelong		!0
 # skip PCX and some DBF by test for for reserved NULL bytes
@@ -424,7 +426,19 @@
 >>>>>>>>>>>>512	ubyte		<0200
 # skip gluon-ffhat-1.0-tp-link-tl-wr1043n-nd-v2-sysupgrade.bin by printable 2nd character
 >>>>>>>>>>>>>513 ubyte		>037
->>>>>>>>>>>>>>0	use		dbase3-memo-print
+# skip few (8/758) Microsoft Event Trace Logs (WBEngine.3.etl Wifi.etl) with valid 1st item like
+# "9600.20369.amd64fre.winblue_ltsb_escrow.220427-1727"
+# "9600.19846.amd64fre.winblue_ltsb_escrow.200923-1735"
+# "10586.494.amd64fre.th2_release_sec.160630-1736"
+# by looking for valid terminating character Ctrl-Z
+>>>>>>>>>>>>>>513 search/0x11E	\032
+# followed by second character Ctrl-Z implies typical DBT
+>>>>>>>>>>>>>>>&0	ubyte	032
+# examples like: angest.dbt
+>>>>>>>>>>>>>>>>0	use	dbase3-memo-print
+>>>>>>>>>>>>>>>&0	ubyte	0
+# no example found here with terminating sequence CTRL-Z + \0
+>>>>>>>>>>>>>>>>0	use	dbase3-memo-print
 # dBASE IV DBT with positive block size
 >>>>>>>20	uleshort	>0
 # dBASE IV DBT with valid block length like 512, 1024
@@ -451,6 +465,11 @@
 >512	string			>\0		\b, 1st item "%s"
 # For DEBUGGING
 #>512	ubelong			x		\b, 1ST item %#8.8x
+#>513	search/0x225		\032		FOUND_TERMINATOR
+#>>&0	ubyte			032		2xCTRL_Z
+# fsadress.dbt has 1 Ctrl-Z terminator followed by nil byte
+#>>&0	ubyte			0		1xCTRL_Z
+
 # https://www.clicketyclick.dk/databases/xbase/format/dbt.html
 #		Print the information of dBase IV DBT memo file
 0	name				dbase4-memo-print
--- a/magic/Magdir/dsf
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#------------------------------------------------------------
-# $File: dsf,v 1.1 2022/01/08 16:29:18 christos Exp $
-# dsf:  file(1) magic for DSD Stream File
-# URL:          https://en.wikipedia.org/wiki/Direct_Stream_Digital
-# Reference:    https://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
-0	string	DSD\x20		DSD Stream File,
->0x30	leshort	1		mono,
->0x30	leshort	2		stereo,
->0x30	leshort	3		three-channel,
->0x30	leshort	4		quad-channel,
->0x30	leshort	5		3.1 4-channel,
->0x30	leshort	6		five-channel,
->0x30	leshort	7		5.1 surround,
->0x30	default	x	
->>0x30	leshort	x		unknown channel format (%d),
->0x38	lelong	2822400		simple-rate,
->0x38	lelong	5644800		double-rate,
->0x38	default	x	
->>0x38	lelong	x		%d Hz,
->0x3c	leshort	1		1 bit,
->0x3c	leshort	8		8 bit,
->0x3c	default	x
->>0x3c	leshort	x		%d bit,
->0x40	lelong	x		%d samples
--- a/magic/Magdir/filesystems
+++ b/magic/Magdir/filesystems
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: filesystems,v 1.150 2022/07/04 16:40:33 christos Exp $
+# $File: filesystems,v 1.152 2022/12/10 20:56:50 christos Exp $
 # filesystems:  file(1) magic for different filesystems
 #
 0	name	partid
@@ -1596,7 +1596,8 @@
 >0x1e	lequad	x			%lld total clusters,
 >0x26	lequad	x			%lld clusters in use
 
-9564	lelong		0x00011954	Unix Fast File system [v1] (little-endian),
+
+0	name		ffsv1
 >8404	string		x		last mounted on %s,
 #>9504	ledate		x		last checked at %s,
 >8224	ledate		x		last written at %s,
@@ -1612,105 +1613,59 @@
 >8320	lelong		0		TIME optimization
 >8320	lelong		1		SPACE optimization
 
-42332	lelong		0x19540119	Unix Fast File system [v2] (little-endian)
->&-1164	string		x		last mounted on %s,
->&-696	string		>\0		volume name %s,
->&-304	leqldate	x		last written at %s,
->&-1167	byte		x		clean flag %d,
->&-1168	byte		x		readonly flag %d,
->&-296	lequad		x		number of blocks %lld,
->&-288	lequad		x		number of data blocks %lld,
->&-1332	lelong		x		number of cylinder groups %d,
->&-1328	lelong		x		block size %d,
->&-1324	lelong		x		fragment size %d,
->&-180	lelong		x		average file size %d,
->&-176	lelong		x		average number of files in dir %d,
->&-272	lequad		x		pending blocks to free %lld,
->&-264	lelong		x		pending inodes to free %d,
->&-664	lequad		x		system-wide uuid %0llx,
->&-1316	lelong		x		minimum percentage of free blocks %d,
->&-1248	lelong		0		TIME optimization
->&-1248	lelong		1		SPACE optimization
-
-66908	lelong		0x19540119	Unix Fast File system [v2] (little-endian)
->&-1164	string		x		last mounted on %s,
->&-696	string		>\0		volume name %s,
->&-304	leqldate	x		last written at %s,
->&-1167	byte		x		clean flag %d,
->&-1168	byte		x		readonly flag %d,
->&-296	lequad		x		number of blocks %lld,
->&-288	lequad		x		number of data blocks %lld,
->&-1332	lelong		x		number of cylinder groups %d,
->&-1328	lelong		x		block size %d,
->&-1324	lelong		x		fragment size %d,
->&-180	lelong		x		average file size %d,
->&-176	lelong		x		average number of files in dir %d,
->&-272	lequad		x		pending blocks to free %lld,
->&-264	lelong		x		pending inodes to free %d,
->&-664	lequad		x		system-wide uuid %0llx,
->&-1316	lelong		x		minimum percentage of free blocks %d,
->&-1248	lelong		0		TIME optimization
->&-1248	lelong		1		SPACE optimization
+9564	lelong		0x00011954	Unix Fast File system [v1] (little-endian),
+>0	use		ffsv1
 
 9564	belong		0x00011954	Unix Fast File system [v1] (big-endian),
 >7168   belong		0x4c41424c	Apple UFS Volume
 >>7186  string		x		named %s,
 >>7176  belong		x		volume label version %d,
 >>7180  bedate		x		created on %s,
->8404	string		x		last mounted on %s,
-#>9504	bedate		x		last checked at %s,
->8224	bedate		x		last written at %s,
->8401	byte		x		clean flag %d,
->8228	belong		x		number of blocks %d,
->8232	belong		x		number of data blocks %d,
->8236	belong		x		number of cylinder groups %d,
->8240	belong		x		block size %d,
->8244	belong		x		fragment size %d,
->8252	belong		x		minimum percentage of free blocks %d,
->8256	belong		x		rotational delay %dms,
->8260	belong		x		disk rotational speed %drps,
->8320	belong		0		TIME optimization
->8320	belong		1		SPACE optimization
+>0	use		\^ffsv1
+
+0	name		ffsv2
+>212	string		x		last mounted on %s,
+>680	string		>\0		volume name %s,
+>1072	leqldate	x		last written at %s,
+>209	byte		x		clean flag %d,
+>210	byte		x		readonly flag %d,
+>1080	lequad		x		number of blocks %lld,
+>1088	lequad		x		number of data blocks %lld,
+>44	lelong		x		number of cylinder groups %d,
+>48	lelong		x		block size %d,
+>52	lelong		x		fragment size %d,
+>1196	lelong		x		average file size %d,
+>1200	lelong		x		average number of files in dir %d,
+>1104	lequad		x		pending blocks to free %lld,
+>1112	lelong		x		pending inodes to free %d,
+>712	lequad		x		system-wide uuid %0llx,
+>60	lelong		x		minimum percentage of free blocks %d,
+>128	lelong		0		TIME optimization
+>128	lelong		1		SPACE optimization
+
+42332	lelong		0x19012038	Unix Fast File system [v2ea] (little-endian)
+>40960	use		ffsv2
+
+42332	lelong		0x19540119	Unix Fast File system [v2] (little-endian)
+>40960	use		ffsv2
+
+42332	belong		0x19012038	Unix Fast File system [v2ea] (little-endian)
+>40960	use		\^ffsv2
 
 42332	belong		0x19540119	Unix Fast File system [v2] (big-endian)
->&-1164	string		x		last mounted on %s,
->&-696	string		>\0		volume name %s,
->&-304	beqldate	x		last written at %s,
->&-1167	byte		x		clean flag %d,
->&-1168	byte		x		readonly flag %d,
->&-296	bequad		x		number of blocks %lld,
->&-288	bequad		x		number of data blocks %lld,
->&-1332	belong		x		number of cylinder groups %d,
->&-1328	belong		x		block size %d,
->&-1324	belong		x		fragment size %d,
->&-180	belong		x		average file size %d,
->&-176	belong		x		average number of files in dir %d,
->&-272	bequad		x		pending blocks to free %lld,
->&-264	belong		x		pending inodes to free %d,
->&-664	bequad		x		system-wide uuid %0llx,
->&-1316	belong		x		minimum percentage of free blocks %d,
->&-1248	belong		0		TIME optimization
->&-1248	belong		1		SPACE optimization
+>40960	use		\^ffsv2
+
+66908	lelong		0x19012038	Unix Fast File system [v2ea] (little-endian)
+>65536	use		ffsv2
+
+66908	lelong		0x19540119	Unix Fast File system [v2] (little-endian)
+>65536	use		ffsv2
+
+66908	belong		0x19012038	Unix Fast File system [v2ea] (little-endian)
+>65536	use		\^ffsv2
 
 66908	belong		0x19540119	Unix Fast File system [v2] (big-endian)
->&-1164	string		x		last mounted on %s,
->&-696	string		>\0		volume name %s,
->&-304	beqldate	x		last written at %s,
->&-1167	byte		x		clean flag %d,
->&-1168	byte		x		readonly flag %d,
->&-296	bequad		x		number of blocks %lld,
->&-288	bequad		x		number of data blocks %lld,
->&-1332	belong		x		number of cylinder groups %d,
->&-1328	belong		x		block size %d,
->&-1324	belong		x		fragment size %d,
->&-180	belong		x		average file size %d,
->&-176	belong		x		average number of files in dir %d,
->&-272	bequad		x		pending blocks to free %lld,
->&-264	belong		x		pending inodes to free %d,
->&-664	bequad		x		system-wide uuid %0llx,
->&-1316	belong		x		minimum percentage of free blocks %d,
->&-1248	belong		0		TIME optimization
->&-1248	belong		1		SPACE optimization
+>65536	use		\^ffsv2
 
 0	ulequad		0xc8414d4dc5523031	HAMMER filesystem (little-endian),
 >0x90	lelong+1	x			volume %d
--- /dev/null
+++ b/magic/Magdir/firmware
@@ -0,0 +1,33 @@
+#------------------------------------------------------------------------------
+# $File: firmware,v 1.3 2022/10/15 15:38:44 christos Exp $
+# firmware:  file(1) magic for firmware files
+#
+
+# https://github.com/MatrixEditor/frontier-smart-api/blob/main/docs/firmware-2.0.md#11-header-structure
+# examples: https://github.com/cweiske/frontier-silicon-firmwares
+0	lelong		0x00001176	
+>4	lelong		0x7c		Frontier Silicon firmware download
+>>8	lelong		x		\b, MeOS version %x
+>>12	string/32/T	x		\b, version %s
+>>40	string/64/T	x		\b, customization %s
+
+# HPE iLO firmware update image
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://www.sstic.org/2018/presentation/backdooring_your_server_through_its_bmc_the_hpe_ilo4_case/
+# iLO1 (ilo1*.bin) or iLO2 (ilo2_*.bin) images
+0               string                  \x20\x36\xc1\xce\x60\x37\x62\xf0\x3f\x06\xde\x00\x00\x03\x7f\x00
+>16             ubeshort                =0xCFDD         HPE iLO2 firmware update image
+>16             ubeshort                =0x6444         HPE iLO1 firmware update image
+# iLO3 images (ilo3_*.bin) start directly with image name
+0               string                  iLO3\x20v\x20   HPE iLO3 firmware update image,
+>7              string                  x               version %s
+# iLO4 images (ilo4_*.bin) start with a signature and a certificate
+0               string                  --=</Begin\x20HP\x20Signed
+>75             string                  label_HPBBatch
+>>5828          string                  iLO\x204
+>>>5732         string                  HPIMAGE\x00     HPE iLO4 firmware update image,
+>>>6947         string                  x               version %s
+# iLO5 images (ilo5_*.bin) start with a signature
+>75             string                  label_HPE-HPB-BMC-ILO5-4096
+>>880           string                  HPIMAGE\x00     HPE iLO5 firmware update image,
+>>944           string                  x               version %s
--- a/magic/Magdir/games
+++ b/magic/Magdir/games
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: games,v 1.25 2022/05/31 18:40:20 christos Exp $
+# $File: games,v 1.29 2022/12/21 15:49:49 christos Exp $
 # games:  file(1) for games
 
 # Fabio Bonelli <fabiobonelli@libero.it>
@@ -293,12 +293,92 @@
 >2	regex/c	GM\\[21\\]			- twix Game
 
 # Epic Games/Unreal Engine Package
-#
-0	lelong		0x9E2A83C1	Unreal Engine Package,
->4	leshort		x		version: %i
->12	lelong		!0		\b, names: %i
->28	lelong		!0		\b, imports: %i
->20	lelong		!0		\b, exports: %i
+# URL: https://docs.unrealengine.com/udk/Three/ContentCooking.html
+#      https://eliotvu.com/page/unreal-package-file-format
+# Little-endian version (such as x86 PC)
+0		lelong		0x9E2A83C1	Unreal Engine package (little-endian)
+!:ext		xxx/tfc/upk/me1/u
+>4		uleshort	!0		\b, version %u
+>>6		uleshort	!0		\b/%03u
+>>0		use		upk_header
+# Big-endian version (such as PS3)
+0		belong		0x9E2A83C1	Unreal Engine package (big-endian)
+!:ext		xxx/tfc
+>6		ubeshort	!0		\b, version %u
+>>4		ubeshort	!0		\b/%03u
+>>0		use		\^upk_header
+
+0		name		upk_header
+# Identify game from version and licensee
+>4		ulelong		0x000002b2	(Alice Madness Returns)
+>4		ulelong		0x002f0313	(Aliens: Colonial Marines)
+>4		ulelong		0x005b021b	(Alpha Protocol)
+>4		ulelong		0x0000032c	(AntiChamber)
+>4		ulelong		0x00200223	(APB: All Points Bulletin)
+>4		ulelong		0x004b02d7	(Bioshock Infinite)
+>4		ulelong		0x00380340	(Borderlands 2)
+>4		ulelong		0x001d02e6	(Bulletstorm)
+>4		ulelong		0x00050240	(CrimeCraft)
+>4		ulelong		0x00000356	(Deadlight)
+>4		ulelong		0x001e0321	(Dishonored)
+>4		ulelong		0x000202a6	(Dungeon Defenders)
+>4		ulelong		0x000901ea	(Gears of War)
+>4		ulelong		0x0000023f	(Gears of War 2)
+>4		ulelong		0x0000033c	(Gears of War 3)
+>4		ulelong		0x0000034e	(Gears of War: Judgement)
+>4		ulelong		0x0004035c	(Hawken)
+>4		ulelong		0x0001034a	(Infinity Blade 2)
+>4		ulelong		0x00000350	(InMomentum)
+>4		ulelong		0x0015037D	(Life Is Strange)
+>4		ulelong		0x000b01a5	(Medal of Honor: Airborne)
+>4		ulelong		0x002b0218	(Mirrors Edge)
+>4		ulelong		0x0000027e	(Monday Night Combat)
+>4		ulelong		0x0000024b	(MoonBase Alpha)
+>4		ulelong		0x002e01d8	(Mortal Kombat Komplete Edition 2605)
+>4		ulelong		0x0000035c	(Painkiller HD)
+>4		ulelong		0x0000034d	(Q.U.B.E)
+>4		ulelong		0x80660340	(Quantum Conundrum)
+>4		ulelong		0x0000035b	(Ravaged)
+>4		ulelong		0x00150340	(Remember Me)
+>4		ulelong		0x00060171	(Roboblitz)
+>4		ulelong		0x00000325	(Rock of Ages)
+>4		ulelong		0x0000032a	(Sanctum)
+>4		ulelong		0x00030248	(Saw)
+>4		ulelong		0x007e0248	(Singularity)
+>4		ulelong		0x00090388	(Soldier Front 2)
+>4		ulelong		0x000701e6	(Stargate Worlds)
+>4		ulelong		0x00000334	(Super Monday Night Combat)
+>4		ulelong		0x000002c2	(The Ball)
+>4		ulelong		0x000e0262	(The Exiled Realm of Arborea or TERA)
+>4		ulelong		0x0000035b	(The Five Cores)
+>4		ulelong		0x00000349	(The Haunted: Hells Reach)
+>4		ulelong		0x00000354	(Unmechanical)
+>4		ulelong		0x035c0298	(Unreal Development Kit)
+>4		ulelong		0x00000200	(Unreal Tournament 3)
+>4		ulelong		0x0000032d	(Waves)
+>4		ulelong		0x003b034d	(XCOM: Enemy Unknown)
+# Newer versions insert more headers
+>4		ulelong&0xFFFF	<249
+>>12		lelong		!0		\b, names: %d
+>>28		lelong		!0		\b, imports: %d
+>>20		lelong		!0		\b, exports: %d
+>4		ulelong&0xFFFF	>248
+>>12		belong&0xFF	!0
+>>>12		string		x		\b, folder "%s"
+>>>>&5		lelong		!0		\b, names: %d
+>>>>&21		lelong		!0		\b, imports: %d
+>>>>&13		lelong		!0		\b, exports: %d
+>>12		belong&0xFF	0
+>>>16		belong&0xFF	!0
+>>>>16		string		x		\b, folder "%s"
+>>>>>&5		lelong		!0		\b, names: %d
+>>>>>&21	lelong		!0		\b, imports: %d
+>>>>>&13	lelong		!0		\b, exports: %d
+>>>16		belong&0xFF	0
+>>>>20		string		x		\b, folder "%s"
+>>>>>&5		lelong		!0		\b, names: %d
+>>>>>&21	lelong		!0		\b, imports: %d
+>>>>>&13	lelong		!0		\b, exports: %d
 
 0	string		ESVG
 >4	lelong		0x00160000
@@ -510,3 +590,31 @@
 >>0	ulelong&0xf	=8	RDR 2,
 >>4	ulelong 	x	%d bytes,
 >>>8	ulelong 	x	%d entries
+
+# Blitz3D Model File Format
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/minetest/B3DExport/blob/master/B3DExport.py
+0	string		BB3D
+>4	lelong		>0
+>>8	lelong		>0	Blitz3D Model
+!:ext	b3d
+>>>8	lelong		x	\b, version %d
+
+# Minetest Schematic File Format
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/minetest/minetest/blob/5.6.1/src/mapgen/mg_schematic.h
+0	string		MTSM	Minetest Schematic
+!:ext	mts
+>4	ubeshort	x	\b, version %d
+>6	ubeshort	x	\b, size [%d
+>8	ubeshort	x	\b, %d
+>10	ubeshort	x	\b, %d]
+
+# MagicaVoxel File Format
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/ephtracy/voxel-model/blob/ee2216c28a78ebb68691dc6cfa9c4ba429117ea2/MagicaVoxel-file-format-vox.txt
+# Note: This format is used in Veloren voxel RPG.
+0	string		VOX\x20
+>4	lelong		>0	MagicaVoxel model
+!:ext	vox
+>>4	lelong		x	\b, version %d
--- a/magic/Magdir/gentoo
+++ b/magic/Magdir/gentoo
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: gentoo,v 1.2 2022/09/12 13:13:28 christos Exp $
+# $File: gentoo,v 1.4 2022/11/29 23:06:09 christos Exp $
 # gentoo:  file(1) magic for gentoo specific formats
 #
 # Summary: Gentoo ebuild Manifest files (GLEP 74)
@@ -36,6 +36,7 @@
 # (<tag>'s already been matched prior to calling)
 0	name	gentoo-manifest
 >&0	regex	[[:space:]]+[[:print:]]+[[:space:]]+[[:digit:]]+[[:space:]]+[[:alnum:]]+[[:space:]]+[[:xdigit:]]{32}	Gentoo Manifest (GLEP 74)
+!:mime	application/vnd.gentoo.manifest
 
 # Summary: Gentoo ebuild and eclass files
 # Reference: https://projects.gentoo.org/pms/8/pms.html
@@ -43,16 +44,20 @@
 0	search/512	EAPI=
 >0	regex		.*\n[\040\t]*EAPI=["']?	Gentoo ebuild
 >>&0	regex		[[:alnum:]+_.-]+	\b, EAPI %s
+!:mime	application/vnd.gentoo.ebuild
 
 0	search/512	@ECLASS:\040		Gentoo eclass
 >&0	string		x			%s
+!:mime	application/vnd.gentoo.eclass
 
 # Summary: Gentoo supplementary package and category metadata files
 # Reference: https://www.gentoo.org/glep/glep-0068.html
 # Submitted by: Michal Gorny <mgorny@gentoo.org>
 0	string		\<?xml
 >0	search/512	\<catmetadata		Gentoo category metadata file
+!:mime	application/vnd.gentoo.catmetadata+xml
 >0	search/512	\<pkgmetadata		Gentoo package metadata file
+!:mime	application/vnd.gentoo.pkgmetadata+xml
 
 # Summary: Gentoo GLEP 78 binary package
 # Reference: https://www.gentoo.org/glep/glep-0078.html
--- a/magic/Magdir/geo
+++ b/magic/Magdir/geo
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: geo,v 1.8 2022/03/24 15:48:58 christos Exp $
+# $File: geo,v 1.10 2022/10/31 13:22:26 christos Exp $
 # Geo- files from Kurt Schwehr <schwehr@ccom.unh.edu>
 
 ######################################################################
@@ -54,7 +54,43 @@
 ######################################################################
 
 # GeoAcoustics - GeoSwath Plus
-4	beshort	0x2002	GeoSwath RDF
+# Update:	Joerg Jenderek
+# URL:		https://www.mbari.org/products/research-software/mb-system/
+# Reference:	http://ccom.unh.edu/sites/default/files/news-and-events/conferences/auv-bootcamp/
+#		GS%2B-6063-BB-GS%2B-Broadcast-Raw-Data-File-Format-Command-Specification.pdf
+# Note:		All data is written using Intel 80x86 byte ordering (LSB to MSB)
+# raw_header_siz; file header size is 544 bytes
+4	beshort	0x2002
+# GRR: line above is too general as it matches also some Microsoft Event Trace Logs *.ETL
+# skip many (63/753) Microsoft Event Trace Logs (AMSITrace.etl lxcore_kernel.etl NotificationUxBroker.052.etl WindowsBackup.4.etl) with invalid "low" ping header size 0
+>6	leshort	>0	GeoSwath RDF
+# skip foo samples with invalid "high" spare bytes
+#>>536	ulequad	=0	OK_THIS_IS_GeoSwath_RDF
+#!:mime	application/octet-stream
+!:mime	application/x-geoswath-rdf
+# http://ccom.unh.edu/sites/default/files/news-and-events/conferences/auv-bootcamp/060116342.rdf
+!:ext	rdf
+# filename; original file name like: "C:\GS+\Projects\Default\Raw Data Files\060116342.rdf"
+>>8	string	x	"%-.512s"
+# version[8]; recording software version number like: 3.16c
+>>527	string	x	\b, version %-.8s
+# creation; unsigned int file creation time; WHAT time format is this? 
+>>0	ulelong	x	\b, creation time %#8.8x
+# raw_ping_header_size; size of ping header in bytes like: 64
+>>6	leshort	!64	\b, ping header size %d
+# frequency; system frequency in hertz like: 500000
+>>520	lelong	x	\b, frequency %d
+# echo_type; Echosounder type index like: 1
+>>524	leshort	x	\b, echo type %#x
+# file_mode; file mode mask (0x00 bathy & sidescan, 0x80 bathy, 0x40 sidescan, 0x20 seismic)
+>>526	ubyte	!0	\b, file mode %#2.2x
+# pps_mode; PPS synch mode like: 2
+>>535	byte	x	\b, pps mode %#x
+# char spare[8]; apparently zeroed
+>>536	ubequad	!0	\b, spare %#16.16llx
+# Ping_number; 1st ping number like: 4944
+>>544	lelong	x	\b, 1st ping number %d
+
 0	string	Start:-	GeoSwatch auf text file
 
 # Seabeam 2100
@@ -88,7 +124,7 @@
 #
 ######################################################################
 
-# IVS - IVS3d.com Tagged Data Represetation
+# IVS - IVS3d.com Tagged Data Representation
 0	string	%%\ TDR\ 2.0	IVS Fledermaus TDR file
 
 # http://www.ecma-international.org/publications/standards/Ecma-363.htm
--- a/magic/Magdir/images
+++ b/magic/Magdir/images
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: images,v 1.227 2022/09/11 20:58:52 christos Exp $
+# $File: images,v 1.236 2022/10/31 13:22:26 christos Exp $
 # images:  file(1) magic for image formats (see also "iff", and "c-lang" for
 # XPM bitmaps)
 #
@@ -179,7 +179,7 @@
 # adding 65 to strength so that Netpbm images comes before "x86 boot sector" or
 # "DOS/MBR boot sector" identified by ./filesystems
 0	name		netpbm
->3	regex/s		=[0-9]{1,50}[\040\t\f\r\n]+[0-9]{1,50}	Netpbm image data
+>3	regex/s		=\^[0-9]{1,50}[\040\t\f\r\n]+[0-9]{1,50}	Netpbm image data
 >>&0	regex		=[0-9]{1,50} 			\b, size = %s x
 >>>&0	regex		=[0-9]{1,50}			\b %s
 
@@ -311,12 +311,12 @@
 0	string		MM\x00\x2a	TIFF image data, big-endian
 !:strength +70
 !:mime	image/tiff
-!:ext	tif,tiff
+!:ext	tif/tiff
 >(4.L)	use		\^tiff_ifd
 0	string		II\x2a\x00	TIFF image data, little-endian
 !:mime	image/tiff
 !:strength +70
-!:ext	tif,tiff
+!:ext	tif/tiff
 >(4.l)	use		tiff_ifd
 
 0	name		tiff_ifd
@@ -625,7 +625,7 @@
 >>8	string		x		"%s"
 # should be point character (2Eh) of version string according to TrID
 #>6	ubyte		!0x2E		\b, at 6 %#x
-# caret character (23h) at the beginning in most or probaly all exanples
+# caret character (23h) at the beginning in most or probably all examples
 #>0	ubyte		!0x23		\b, starting with character %#x
 # URL: 		http://fileformats.archiveteam.org/wiki/DeskMate_Draw
 #		http://en.wikipedia.org/wiki/Deskmate
@@ -652,7 +652,86 @@
 >24	string		SunGKS		\b, SunGKS
 
 # CGM image files
-0	string		BEGMF		clear text Computer Graphics Metafile
+# Update:	Joerg Jenderek
+# URL: 		http://fileformats.archiveteam.org/wiki/CGM
+#		https://en.wikipedia.org/wiki/Computer_Graphics_Metafile
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/c/cgm-ct.trid.xml
+#		http://standards.iso.org/ittf/PubliclyAvailableStandards/c032381_ISO_IEC_8632-4_1999(E).zip
+# Note:		called "Computer Graphics Metafile (Clear Text)" by TrID and
+#		"Computer Graphics Metafile ASCII" by DROID or CGM by XnView
+#		verified by LibreOffice and partly by XnView `nconvert -info *.CGM`
+# According to TrID only letter B and M are always upcased and by DROID often only B is upcased for command BEGIN METAFILE
+0	string/c	begmf
+# skip SOME DROID fmt-301-signature-id-359.cgm fmt-301-signature-id-361.cgm fmt-302-signature-id-364.cgm
+# fmt-302-signature-id-365.cgm x-fmt-142-signature-id-350.cgm x-fmt-142-signature-id-351.cgm
+>5	short		!0
+# skip other versions of DROID fmt-301-signature-id-359.cgm fmt-301-signature-id-361.cgm fmt-302-signature-id-364.cgm
+# fmt-302-signature-id-365.cgm x-fmt-142-signature-id-350.cgm x-fmt-142-signature-id-351.cgm
+>>5	short		!0xABab		clear text Computer Graphics Metafile
+# https://reposcope.com/mimetype/image/cgm
+!:mime	image/cgm
+!:ext	cgm
+# SF:NAME like: 'metafile example';
+>>>5	string		x		%s
+# look for command METAFILE VERSION (MFVERSION <SOFTSEP> <I:VERSION>)
+>>>2	search/128/c	mfversion
+#>>>>&0	ubyte		x		SOFTSEP=%#x
+# version like: 1 3 4
+>>>>&1	ubyte		>0x31		\b, version %c
+# Summary:	Computer Graphics Metafile (binary)
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/c/cgm-bin.trid.xml
+#		https://standards.iso.org/ittf/PubliclyAvailableStandards/c032380_ISO_IEC_8632-3_1999(E).zip
+# Note:		called "Computer Graphics Metafile (binary)" by TrID and DROID or CGM by XnView
+#		verified by LibreOffice and partly by XnView `nconvert -info *.CGM`
+# look for BEGIN METAFILE (element Class 0 and ID 1 and "random" Parameter) that is binary C C C C 0 0 0 0 0 0 1 P P P P P
+0	ubeshort&0xFFe0		0x0020
+# skip SOME DROID fmt-303-signature-id-368.cgm fmt-304-signature-id-369.cgm fmt-305-signature-id-370.cgm fmt-306-signature-id-371.cgm
+# with containing only 28 bytes
+>28	ubyte			x
+# look for METAFILE VERSION (element class 1 and id 1 and parameter P1 with length 2) that is binary 0 0 0 1 i i i i i i 1 P P P 1 P
+# with "low" version; 2nd worst case argentin.cgm with parameter length 56
+# worst MS.CGM
+#>>2	search/73/b		\x10\x22\0	binary Computer Graphics Metafile
+>>2	search/128/b		\x10\x22\0	binary Computer Graphics Metafile
+!:mime	image/cgm
+!:ext	cgm
+# metafile 2 byte version number like: 1 (most) 2 3 4
+>>>&-1	ubeshort		>1		\b, version %u
+# length number of 1st parameter octets in range 0 to 30 implies short command
+>>>0	ubeshort&0x001F		<31		\b, parameter length %u
+# length of string like: 8 9 10 11 12 29
+#>>>>2		ubyte		x		\b, %u BYTES (SHORT)
+# string like: 'HiJaak 2' 'Example 1' 'sahara.cgm' 'MASTERCLIPS--Art Of Business '
+>>>>2		pstring		>\0		'%s'
+# after 1st short command with even parameter length comes 2nd command like: 1022h 0010h (EAF00010.CGM 'HiJaak 2' FLOPPY2.CGM TIGER.CGM 'B:\TIGER.CGM')
+>>>>0  		ubeshort&0x0001	=0
+>>>>>(2.b+3)	ubeshort	!0x1022		\b, 2nd command %#4.4x (short even)
+# after 1st short command with odd parameter length comes nil padding byte followed 2nd command like: 1022h
+>>>>0  		ubeshort&0x0001	=1
+#>>>>>(2.b+3)	ubyte		!0		\b, PADDING %#x
+>>>>>(2.b+4)	ubeshort	!0x1022		\b, 2nd command %#4.4x (short odd)
+# 11111 binary (decimal 31) in the parameter field indicates that the command is in long-form
+>>>0	ubeshort&0x001F		=0x1F
+# bit 15 is partition flag with 1 for 'not-last' partition and 0 for 'last' partition
+>>>>2  		ubeshort&0x8000	!0		\b, partition flag %#4.4x
+# bits 0 to 14 is parameter list length; the number of following parameter octets; range 0 to 32767
+# length of 1st long command parameter like: 53
+>>>>2  		ubeshort&0x7Fff	x		\b, parameter length %u (long)
+# The two header words are then followed by lenghth of 1st string like: 52
+#>>>>4		ubyte		x		\b, %u BYTES
+# string like: 'K:\PROJECTS\GRAPHICS\DWKS3.5\CLIPART\FLAGS\Italy.cgm'
+>>>>4		pstring/B	x		'%s'
+# odd long parameter length implies single null padding octet to start command on word boundary
+>>>>2  		ubeshort&0x0001	=1
+# after 1st long command with odd parameter length comes nil padding byte followed by 2nd command like: 1022h
+#>>>>>(4.b+5)		ubyte	!0		\b, PADDING %#x
+>>>>>(4.b+6)		ubeshort !0x1022	\b, 2nd command %#4.4x (long odd)
+# even long parameter length implies next command directly is following
+>>>>2  		ubeshort&0x0001	=0
+# after 1st long command with even parameter length comes 2nd command like: 1022h 0x1054 (MS.CGM)
+>>>>>(4.b+5)	ubeshort	!0x1022		\b, 2nd command %#4.4x (long even)
+# look for END METAFILE (element class 0 and id 2 and 0 parameter) that is binary 0 0 0 0 i i i i i 1 i P P P P P
+>>>-2	ubeshort		!0x0040		\b, NOT_FOUND_END_METAFILE
 
 # MGR bitmaps  (Michael Haardt, u31b3hs@pool.informatik.rwth-aachen.de)
 0	string	yz	MGR bitmap, modern format, 8-bit aligned
@@ -1138,7 +1217,7 @@
 0	string			/*\040
 # 9 byte c-comment "/* XPM */" not at the beginning like: mozicon16.xpm mozicon50.xpm (thunderbird)
 >0	search/0xCE		/*\ XPM\ */
-# skip DROID x-fmt-208-signature-id-620.xpm by looking for char aray without explict length
+# skip DROID x-fmt-208-signature-id-620.xpm by looking for char array without explict length
 # and match mh-logo.xpm (emacs)
 >>&0		search/1249	[]
 >>>0		use		xpm-image
@@ -1146,7 +1225,7 @@
 >0	default			x
 # words are separated by a white space which can be composed of space and tabulation characters
 >>0		search/0x52	static\040char\040
-# skip debug.c testmlc.c by looking for char aray without explict length
+# skip debug.c testmlc.c by looking for char array without explict length
 # https://www.clamav.net/downloads/production/clamav-0.104.2.tar.gz
 # clamav-0.104.2\libclammspack\mspack\debug.c 
 >>>&0		search/64	[]
@@ -1459,22 +1538,22 @@
 # skip g3test.g3 by test for unused bits of 2nd color entry
 >>4		ubeshort&0xF000	0
 #>>>0		beshort	x	1ST_VALUE=%x
->>>-0		offset	x	FILE_SIZE=%lld
+#>>>-0		offset	x	FILE_SIZE=%lld
 # standard DEGAS low-res uncompressed bitmap *.pi1 with file size 32034
->>>-0		offset	=32034	VARIANT_STANDARD
+>>>-0		offset	=32034
 #>>>>0		beshort	x	1st_VALUE=%x
 # like: 8ball.pi1 teddy.pi1 sonic01.pi1 
 >>>>0		use		degas-bitmap
 # about 61 DEGAS Elite low-res uncompressed bitmap *.pi1 with file size 32066
->>>-0		offset	=32066	VARIANT_ELITE
+>>>-0		offset	=32066
 # like: spider.pi1 pinkgirl.pi1 frog3.pi1
 >>>>0		use		degas-bitmap
 # about 55 DEGAS Elite low-res uncompressed bitmap *.pi1 with file size 32128
->>>-0		offset	=32128	VARIANT_3
+>>>-0		offset	=32128
 # like: mountain.pi1 bigspid.pi1 alf33.pi1
 >>>>0		use		degas-bitmap
 # 1 DEGAS Elite low-res uncompressed bitmap *.pi1 with file size 44834
->>>-0		offset	=44834	VARIANT_4
+>>>-0		offset	=44834
 # like: kenshin.pi1
 >>>>0		use		degas-bitmap
 # DEGAS mid-res uncompressed bitmap *.pi2 (strength=50) after GEM Images like:
@@ -1483,19 +1562,17 @@
 #!:strength +0
 # skip many control files like gnucash-4.8.setup.exe.aria2 by test for non black in 4 palette entries
 >2		quad		!0
-# skip control file load-v0001.aria2 by test for unused bits of 5th color palette entry
->>10		ubeshort&0xF000	0
-# skip many GEM Image data like DANCER.IMG GAMEOVR4.IMG SHIP.IMG by test for unused bits of 8th color palette entry
->>>16		ubeshort&0xF000	0
-# skip many GEM Image data like BEETHVEN.IMG CABINETS.IMG MEMO.IMG by test for unused bits of 14th color palette entry
->>>>28		ubeshort&0xF000	0
-# skip few GEM Image data like CHURCH.IMG by test for unused bits of 15th color palette entry
->>>>>30		ubeshort&0xF000	0
-# skip many GEM Image data like TIGER.IMG TURKEY.IMG XMAS.IMG by test for unused bits of 16th color palette entry
->>>>>>32	ubeshort&0xF000	0
-# skip GEM Image data like clinton.img by test for existing bytes at the end
->>>>>>>32026	quad		x
->>>>>>>>0	use		degas-bitmap
+# skip control file load-v0001.aria2 and many GEM Image data like
+# GAMEOVR4.IMG BEETHVEN.IMG CHURCH.IMG TURKEY.IMG clinton.img
+# by test for valid file sizes
+# standard DEGAS mid-res uncompressed bitmap *.pi2 with file size 32034
+>>-0		offset	=32034
+# (39/41) like: GEMINI03.PI2 ST_TOOLS.PI2 TBX_DEMO.PI2
+>>>0		use		degas-bitmap
+# few DEGAS Elite mid-res uncompressed bitmap *.pi2 with file size 32066
+>>-0		offset	=32066
+# (2/41) like: medres.pi2
+>>>0		use		degas-bitmap
 # DEGAS high-res uncompressed bitmap *.pi3
 0	beshort		0x0002
 # skip Intel ia64 COFF msvcrt.lib by test for unused bits of 1st atari color palette entry
@@ -1515,8 +1592,12 @@
 # 00000000 "LEREDACT.PI3" 03730773 "TBX_DEMO.PI3"
 #>>>>&8		ubelong			x	\b, LAST CHAR+NIL %8.8x
 >>>>&8		ubelong&0xff00ffFF	!0
+# skip many Adobe Photoshop Color swatch (ANPA-Farben.aco TOYO-Farbsystem.aco) with invalid 3rd color entry (1319 2201 2206 21f5 2480 24db 25fd)
+>>>>>6		ubeshort&0xF000	0
+# skip few Adobe Photoshop Color swatch (FOCOLTONE-Farben.aco "PANTONE process coated.aco") with invalid 4th color entry  (ffff)
+>>>>>>8		ubeshort&0xF000	0
 # many DEGAS bitmap like: ARABDEMO.PI3 ELMRSESN.PI3 GEMVIEW.PI3 LEREDACT.PI3 PICCOLO.PI3 REPRO_JR.PI3 ST_TOOLS.PI3 TBX_DEMO.PI3 evgem7.pi3
->>>>>0		use		degas-bitmap
+>>>>>>>0	use		degas-bitmap
 # test for last character of Adobe PhotoShop Brush UTF16-LE string and terminating nul char
 >>>>&8		ubelong&0xff00ffFF	=0
 # select last DEGAS bitmaps by invalid last char of brush note like BASICNES.PI3 DB_HELP.PI3 DB_WRITR.PI3 LEREDACT.PI3
@@ -1528,13 +1609,23 @@
 0		beshort			0x8000
 # skip lif files handled via ./lif by test for unused bits of 1st palette entry
 >2		ubeshort&0xF000		0
->>0		use		degas-bitmap
+# skip CRI ADX ADPCM audio (R04HT.adx R03T-15552.adx) with 44100 Hz misinterpreted as 5th color entry value AC44h
+>>10		ubeshort&0xF000		0
+# skip few (fmt-840-signature-id-1195.adx fmt-840-signature-id-1199.adx) by test for 4 first non black colors in palette entries
+>>>2		quad			!0
+>>>>0		use		degas-bitmap
 # DEGAS mid-res compressed bitmap *.pc2 like: abydos.pc2 ARTIS3.PC2 SMTHDRAW.PC2 STAR_2K.PC2 TX2_DEMO.PC2
 0		beshort			0x8001
->0		use		degas-bitmap
+# skip many (1274/1369) PostScript Type 1 font (DarkGardenMK.pfb coupbi.pfb MONOBOLD.PFB) with invalid 1st atari color palette entry 5506 5b06 6906 7906 7e06 fb15
+>2		ubeshort&0xF000		0
+# skip some (95/1369) PostScript Type 1 font (fmt-525-signature-id-816.pfb LUXEMBRG.PFB) with invalid 3rd atari color palette entry 2521
+>>6		ubeshort&0xF000		0
+>>>0		use		degas-bitmap
 # DEGAS high-res compressed bitmap *.pc3 like: abydos.pc3 COYOTE.PC3 ELEPHANT.PC3 TX2_DEMO.PC3 SMTHDRAW.PC3
 0		beshort			0x8002
->0		use		degas-bitmap
+# skip some (36/212) Python Pickle (factor_cache.pickle environment.pickle) with invalid 1st atari color entry (2863 6363 7d71)
+>2		ubeshort&0xF000		0
+>>0		use		degas-bitmap
 # display information of Atari DEGAS and DEGAS Elite bitmap images
 0	name		degas-bitmap
 >0	ubyte		x		Atari DEGAS
@@ -1741,6 +1832,113 @@
 >>>6  belong  x	 0x%8.8x
 >>>6  beshort x   \b%4.4x
 
+# From:		Joerg Jenderek
+# URL:		https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
+#		http://fileformats.archiveteam.org/wiki/Photoshop
+# Reference:	http://www.nomodes.com/aco.html
+# Note:		registers as Photoshop.SwatchesFile for Photoshop.exe on Windows
+# check for valid versions like: 2 (newest) 1 (old) 0 (oldest no examples)
+0		ubeshort				<3
+# skip few Atari DEGAS med-res bitmap (DIAGRAM1.PI2) and many ISO 9660 CD-ROM by check for invalid low color numbers (0)
+>2		ubeshort				>0
+# skip few Targa (bmpsuite-15col.tga rgb24_top_left_colormap.tga) by check for invalid high color space ID (F0 1D)
+>>4		ubeshort				<16
+# skip many (69/327) Targa image *.TGA by check of accessing near the ending of first color space section (size=nc*5*2)
+>>>(2.S*10)	ubelong					x
+# RGB branch for Adobe Photoshop Color swatch
+>>>>4		ubeshort				=0
+# skip many (220/327) Targa by check of for invalid high RGB color z value (hexadecimal 2 3 2e03 4600 5e04 7502 8002 8b05 c700)
+>>>>>12			ubeshort			=0
+# RGB branch for Adobe Photoshop Color swatch for older versions
+>>>>>>0				ubeshort		<2
+>>>>>>>0				use		adobe-aco
+# RGB branch for Adobe Photoshop Color swatch for newer version 2
+>>>>>>0				ubeshort		=2
+# skip many (74/176) Atari DEGAS hi-res bitmap (*.PI3) by check for invalid low color name length (0)
+>>>>>>>16				ubeshort	>0
+>>>>>>>>0					use	adobe-aco
+# non RGB branch for Adobe Photoshop Color swatch
+>>>>4		ubeshort				!0
+# non RGB branch for Adobe Photoshop Color swatch for older versions
+>>>>>0			ubeshort			<2
+# skip many GEM Image (CHURCH.IMG TIGER.IMG) by check for invalid second high color space ID (55 114 143 157 256 288 450)
+>>>>>>14			ubeshort		<16
+>>>>>>>0				use		adobe-aco
+# non RGB branch for Adobe Photoshop Color swatch for newer version 2
+>>>>>0			ubeshort			=2
+# skip few Atari DEGAS hi-res bitmap (pal1wb-blue.pi3) and few ABR by check for invalid "high" nil bytes (7) before color name length
+>>>>>>14			ubeshort		=0
+>>>>>>>0				use		adobe-aco
+#	display Adobe Photoshop Color swatch file information (version, number of colors, color spaces, coordinates, names)
+0	name		adobe-aco
+>0		ubeshort				x		Adobe Photoshop Color swatch, version %u
+#!:mime		application/octet-stream
+!:mime		application/x-adobe-aco
+!:apple		????8BCO
+!:ext		aco
+>0		ubeshort				<2
+>>(2.S*10)	ubelong					x
+# version 2 section after version 1 section
+>>>&0		ubeshort				2		and 2
+# nc; number of colors like: 20 50 86 88 126 204 300 1050 1137 1280 2092 3010 4096
+>2		ubeshort				x		\b, %u colors
+# maybe last 4 bytes of first section (probably y z color value) like: 0 0x66660000 0xfe700000 0xffff0000
+#>(2.S*10)	ubelong					x		1ST_SECTION_END=%#8.8x
+>0		ubeshort				<2		\b; 1st
+# first older Adobe Photoshop Color entry
+>>4			use				aco-color
+>>>2				ubeshort		>1		\b; 2nd
+# second older Adobe Photoshop Color entry
+>>>>14					use		aco-color
+>0		ubeshort				=2		\b; 1st
+# first new Adobe Photoshop Color entry
+>>4			use				aco-color-v2
+>>>2				ubeshort		>1		\b; 2nd
+# jump first color name length words
+>>>>(16.S*2)				ubequad		x
+# second new Adobe Photoshop Color entry
+>>>>>&10					use	aco-color-v2
+#	display Adobe Photoshop Color entry (color space, color coordinates)
+0	name		aco-color
+# each color spec entry occupies five words
+# color space: 0~RGB 1~HSB 2~CMYK 3~Pantone 4~Focoltone 5~Trumatch 6~Toyo 7~Lab 8~Grayscale 9?~wideCMYK 10~HKS ...
+#>0		ubeshort				x		COLOR_ENTRY
+>0		ubeshort				0		RGB
+>0		ubeshort				1		HSB
+>0		ubeshort				2		CMYK
+>0		ubeshort				3		Pantone
+>0		ubeshort				4		Focoltone
+>0		ubeshort				5		Trumatch
+>0		ubeshort				6		Toyo
+>0		ubeshort				7		Lab
+>0		ubeshort				8		Grayscale
+>0		ubeshort				9		wide CMYK
+>0		ubeshort				10		HKS
+# unofficial
+# >0		ubeshort				12		foo
+# >0		ubeshort				13		bar
+# >0		ubeshort				14		FOO
+# >0		ubeshort				15		BAR
+>0		ubeshort				x		space (%u)
+# color coordinate w
+>2		ubeshort				x		\b, w %#x
+# color coordinate x
+>4		ubeshort				x		\b, x %#x
+# color coordinate y
+>6		ubeshort				x		\b, y %#x
+# color coordinate z; zero for RGB space
+>8		ubeshort				x		\b, z %#x
+#	display Adobe Photoshop Color entry version 2 (color space, color coordinates names)
+0	name		aco-color-v2
+>0		use					aco-color
+#>10		ubeshort				x		\b, NUL_BYTES %#x
+# color name length plus one (len+1) like: 7 8 9 13 14 15 16 17 22 26
+#>>12		ubeshort			 	x		\b, LENGTH %u
+>>12		ubeshort-1				x		\b, %u chars
+# len words; UTF-16 representation of the color name like: "DIC 1s" "PANTONE Process Yellow PC"
+>>14		bestring16				x		"%s"
+# followed by nil word
+
 # XV thumbnail indicator (ThMO)
 # URL:		https://en.wikipedia.org/wiki/Xv_(software)
 # Reference:	http://fileformats.archiveteam.org/wiki/XV_thumbnail
@@ -2537,6 +2735,7 @@
 
 # BS encoded bitstreams
 2		uleshort	0x3800		BS image,
+# GRR: the above line is also true for binary Computer Graphics Metafile SAB00012.CGM with long parameter length 56 (=38h)
 >6		uleshort	x		Version %d,
 >4		uleshort	x		Quantization %d,
 >0		uleshort	x		(Decompresses to %d words)
--- a/magic/Magdir/intel
+++ b/magic/Magdir/intel
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: intel,v 1.22 2022/04/02 14:47:42 christos Exp $
+# $File: intel,v 1.23 2022/10/31 13:22:26 christos Exp $
 # intel:  file(1) magic for x86 Unix
 #
 # Various flavors of x86 UNIX executable/object (other than Xenix, which
@@ -141,7 +141,7 @@
 #	e80d0fcbh	PXE-Intel.rom
 #	b8004875h	orchid.bin
 >>3	ubelong			x	%#8.8x
-# For misidetified raspberry pi pieeprom-*.bin like: 0xf00f
+# For misidentified raspberry pi pieeprom-*.bin like: 0xf00f
 #>2	ubeshort		x	\b, AT 2 %#4.4x
 ################################################################################
 #		new sections for BIOS (ia32) ROM Extension
@@ -230,12 +230,12 @@
 # PCI data structure length like: 24h 28h
 >>(24.s+0xA)	uleshort	>0x28	\b, length %u
 # PCI data structure revision like: 0 3
->>(24.s+0xC)	ubyte		>0	\b, revison %u
+>>(24.s+0xC)	ubyte		>0	\b, revision %u
 # image length (hexadecimal) in multiple of 512 bytes like: 54 56 68 6a 76 78 7c 7d 7e 7f 80 81 83
 # Apparently this gives the same information as given by byte at offset 2 but as 16-bit
 #>>(24.s+0x10)	uleshort	x	\b, length %u*512
 # revision level of code/data like: 0 1 201h 502h
->>(24.s+0xC)	ubyte		>1	\b, code revison %#x
+>>(24.s+0xC)	ubyte		>1	\b, code revision %#x
 # code type: 0~Intel x86/PC-AT compatible 1~Open firmware standard for PCI42 FF~Reserved
 >>(24.s+0x14)	ubyte		>0	\b, code type %#x
 # last image indicator; bit 7 indicates "last image"; bits 0-6 are reserved
--- a/magic/Magdir/jpeg
+++ b/magic/Magdir/jpeg
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: jpeg,v 1.37 2022/06/17 18:03:35 christos Exp $
+# $File: jpeg,v 1.38 2022/12/02 17:42:04 christos Exp $
 # JPEG images
 # SunOS 5.5.1 had
 #
@@ -239,8 +239,7 @@
 # Reference:	http://mark0.net/download/triddefs_xml.7z/defs/b/bitmap-jxl.trid.xml
 # Note:         called by TrID "JPEG XL bitmap"
 0	string	\xff\x0a				JPEG XL codestream
-#!:mime  image/jxl
-!:mime	image/x-jxl
+!:mime	image/jxl
 !:ext jxl
 
 # JPEG XL (transcoded JPEG file)
@@ -249,6 +248,5 @@
 # Reference:	http://mark0.net/download/triddefs_xml.7z/defs/b/bitmap-jxl-iso.trid.xml 
 # Note:         called by TrID "JPEG XL bitmap (ISOBMFF)"
 0	string	\x00\x00\x00\x0cJXL\x20\x0d\x0a\x87\x0a	JPEG XL container
-#!:mime  image/jxl
-!:mime	image/x-jxl
+!:mime	image/jxl
 !:ext jxl
--- a/magic/Magdir/lif
+++ b/magic/Magdir/lif
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: lif,v 1.10 2021/04/26 15:56:00 christos Exp $
+# $File: lif,v 1.11 2022/10/19 20:15:16 christos Exp $
 # lif:  file(1) magic for lif
 #
 # (Daniel Quinlan <quinlan@yggdrasil.com>)
@@ -16,9 +16,9 @@
 >14	beshort		=0
 # skip MUNCHIE.PC1 BOARD.PC1 ENEMIES.PC1 by test for low version number
 >>20	ubeshort	<0x0100
-# skip DEGAS MUNCHIE.PC1 BOARD.PC1 ENEMIES.PC1 by test for ASCII like volume name
-#>>>2	ubelong		>0x2020201F
->>>0	use		lif-file
+# skip DROID fmt-840-signature-id-1195.adx fmt-840-signature-id-1199.adx by test for ASCII like volume name
+>>>2	ubelong		>0x2020201F
+>>>>0	use		lif-file
 0	name		lif-file
 # LIF ID
 >0	beshort		x		lif file
@@ -27,6 +27,7 @@
 !:ext	lif/hpi/dat
 # volume label; A-Z 0-9 _ ; default are 6 spaces
 >2	string		x		"%.6s"
+#>2	ubelong		x		LABEL=%8.8x
 # version number; 0 for systems without extensions or 1 for model 64000
 >20	ubeshort	x		\b, version %u
 # LIF identifier; 010000 for system 3000
--- a/magic/Magdir/linux
+++ b/magic/Magdir/linux
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: linux,v 1.82 2022/09/07 11:23:44 christos Exp $
+# $File: linux,v 1.84 2022/11/29 23:10:29 christos Exp $
 # linux:  file(1) magic for Linux files
 #
 # Values for Linux/i386 binaries, from Daniel Quinlan <quinlan@yggdrasil.com>
@@ -67,8 +67,8 @@
 >16	lelong		x		%d characters,
 >12	lelong&0x01	0		no directory,
 >12	lelong&0x01	!0		Unicode directory,
->24	lelong		x		%d
->28	lelong		x		\bx%d
+>28	lelong		x		%d
+>24	lelong		x		\bx%d
 
 # Linux swap and hibernate files
 # Linux kernel: include/linux/swap.h
@@ -492,9 +492,12 @@
 0		lelong		0x58313116	CRIU inventory
 
 # Kdump compressed dump files
-# https://sourceforge.net/p/makedumpfile/code/ci/master/tree/IMPLEMENTATION
+# https://github.com/makedumpfile/makedumpfile/blob/master/IMPLEMENTATION
 
-0		string		KDUMP          	Kdump compressed dump
+0		string		KDUMP\x20\x20\x20	Kdump compressed dump
+>0		use		kdump-compressed-dump
+
+0		name		kdump-compressed-dump
 >8		long		x		v%d
 >12		string		>\0		\b, system %s
 >77		string		>\0		\b, node %s
@@ -503,6 +506,12 @@
 >272		string		>\0		\b, machine %s
 >337		string		>\0		\b, domain %s
 
+# Flattened format
+0		string		makedumpfile
+>16		bequad		1
+>>0x1010	string		KDUMP\x20\x20\x20	Flattened kdump compressed dump
+>>>0x1010	use		kdump-compressed-dump
+
 # Device Tree files
 0		search/1024	/dts-v1/	Device Tree File (v1)
 # beat c code
--- a/magic/Magdir/macintosh
+++ b/magic/Magdir/macintosh
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: macintosh,v 1.32 2021/04/26 15:56:00 christos Exp $
+# $File: macintosh,v 1.36 2022/12/06 18:45:20 christos Exp $
 # macintosh description
 #
 # BinHex is the Macintosh ASCII-encoded file format (see also "apple")
@@ -95,7 +95,10 @@
 # MacBinary format (Eric Fischer, enf@pobox.com)
 # Update: Joerg Jenderek 
 # URL: https://en.wikipedia.org/wiki/MacBinary
+#	http://fileformats.archiveteam.org/wiki/MacBinary
 # Reference: https://files.stairways.com/other/macbinaryii-standard-info.txt
+# Note:	verified by macutils `macunpack -i -v BBEdit4.0.sit.bin` and
+#	`deark -l -d -m macbinary G3FirmwareUpdate1.1.smi.bin`
 #
 # Unfortunately MacBinary doesn't really have a magic number prior
 # to the MacBinary III format.
@@ -114,19 +117,19 @@
 >>>>74	byte	0
 # zero fill, must be zero for compatibility
 >>>>>82	byte	0
+# skip few DEGAS mid-res uncompressed bitmap (GEMINI03.PI2 CODE_RAM.PI2) with "too high" file names ffffff88 ffff4f00
+>>>>>>2	ubelong		<0xffff0000
 # MacBinary I		test for valid version numbers
->>>>>>122	ubeshort	0
-# additional check for creation date after 1 Jan 1970 ~ 7C25B080h
-#>>>>>>>91	ubelong		>0x7c25b07F
+>>>>>>>122	ubeshort	0
 # additional check for undefined header fields in MacBinary I
-#>>>>>>>101	ulong		0
->>>>>>>0	use	mac-bin
+#>>>>>>>>101	ulong		0
+>>>>>>>>0	use	mac-bin
 # MacBinary II		the newer versions begins at 129
->>>>>>122	ubeshort	0x8181
->>>>>>>0	use	mac-bin
+>>>>>>>122	ubeshort	0x8181
+>>>>>>>>0	use	mac-bin
 # MacBinary III with MacBinary II to read
->>>>>122	ubeshort	0x8281
->>>>>>0	use	mac-bin
+>>>>>>122	ubeshort	0x8281
+>>>>>>>0	use	mac-bin
 
 #	display information of MacBinary file
 0	name		mac-bin
@@ -139,7 +142,7 @@
 !:mime	application/x-macbinary
 !:apple	PSPTBINA
 !:ext	bin/macbin
-# THIS SHOULD NEVER HAPPEN! Maybe another file type is misidetified as MacBinary
+# THIS SHOULD NEVER HAPPEN! Maybe another file type is misidentified as MacBinary
 #>1	ubyte	>63		\b, name length %u too BIG!
 #>122	ubeshort	x	\b, version %#x
 # Finder flags if not 0
@@ -180,12 +183,16 @@
 # 124	beshort				# checksum
 #>124	ubeshort	!0		\b, CRC %#x
 # creation date in seconds since MacOS epoch start. So 1 Jan 1970 ~ 7C25B080
->91	beldate-0x7C25B080	x	\b, %s
-# THIS SHOULD NEVER HAPPEN! Maybe another file type is misidetified or time overflow
+# few (31/1247) examples (hinkC4.0.sitx.bin InternetExplorer5.1.smi.bin G3FirmwareUpdate1.1.smi.bin Firewire2.3.3.smi.bin LR2image.bin) contain zeroed date fields
+>91	long		!0
+>>91	beldate-0x7C25B080	x	\b, %s
+# THIS SHOULD NEVER HAPPEN! Maybe another file type is misidentified or time overflow
 >91	ubelong		<0x7c25b080	INVALID date
-#>91	belong-0x7C25B080	x	\b, DEBUG DATE %d
+# reported date seconds by deark
+#>91	ubelong		x		deark-DATE=%u
 # last modified date
->95	beldate-0x7C25B080	x	\b, modified %s
+>95	long		!0
+>>95	beldate-0x7C25B080	x	\b, modified %s
 # Apple creator+typ if not null
 # file creator (normally expressed as four characters)
 >69	ulong			!0	\b, creator
@@ -197,6 +204,7 @@
 # length of data segment
 >83	ubelong			!0	\b, %u bytes
 # filename (in the range 1-63)
+# like "BBEdit4.0.sit" "Archive.sitx" "MacPGP 2.2  (.sea)"
 >1	pstring			x	"%s"
 # print 1 space and then at offset 128 inspect data fork content if it has one
 >83	ubelong			!0	\b 
@@ -447,7 +455,7 @@
 >>>0x412	beshort			x	number of blocks: %d,
 >>>0x424	pstring			x	volume name: %s
 
-0x400	beshort			0x482B		Macintosh HFS Extended
+0	name			hfsplus
 >&0	beshort			x		version %d data
 >0	beshort			0x4C4B		(bootable)
 >0x404	belong			^0x00000100	(mounted)
@@ -466,6 +474,11 @@
 >&42	belong			x		number of blocks: %d,
 >&46	belong			x		free blocks: %d
 
+0x400	beshort			0x482B		Apple HFS Plus
+>&0	use			hfsplus
+0x400	beshort			0x4858		Apple HFS Plus Extended
+>&0	use			hfsplus
+
 ## AFAIK, only the signature is different
 # same as Apple Partition Map
 # GRR: This magic is too weak, it is just "TS"
@@ -490,14 +503,3 @@
 # From: Remi Mommsen <mommsen@slac.stanford.edu>
 0		string		BOMStore	Mac OS X bill of materials (BOM) file
 
-# From: Adam Buchbinder <adam.buchbinder@gmail.com>
-# URL: https://en.wikipedia.org/wiki/Datafork_TrueType
-# Derived from the 'fondu' and 'ufond' source code (fondu.sf.net). 'sfnt' is
-# TrueType; 'POST' is PostScript. 'FONT' and 'NFNT' sometimes appear, but I
-# don't know what they mean.
-0	belong	0x100
->(0x4.L+24)	beshort	x
->>&4	belong	0x73666e74	Mac OSX datafork font, TrueType
->>&4	belong	0x464f4e54	Mac OSX datafork font, 'FONT'
->>&4	belong	0x4e464e54	Mac OSX datafork font, 'NFNT'
->>&4	belong	0x504f5354	Mac OSX datafork font, PostScript
--- a/magic/Magdir/mail.news
+++ b/magic/Magdir/mail.news
@@ -1,5 +1,5 @@
 #------------------------------------------------------------------------------
-# $File: mail.news,v 1.29 2022/06/17 18:02:19 christos Exp $
+# $File: mail.news,v 1.30 2022/10/31 13:22:26 christos Exp $
 # mail.news:  file(1) magic for mail and news
 #
 # Unfortunately, saved netnews also has From line added in some news software.
@@ -65,7 +65,7 @@
 # other ID (like 02900000h) or TnefVersion ID (idTnefVersion=06900800h)
 >7	ubelong		!0x06900800	\b, 1st id %#8.8x
 >7	ubelong		=0x06900800
-# TnefVersion lenght like: 4
+# TnefVersion length like: 4
 >>11	ulelong		!4		\b, TnefVersion length %x
 # TNEFVersionData; TnefVersion data like: 00010000h
 >>15	ulelong		!0x00010000h	\b, version %#8.8x
--- a/magic/Magdir/mathematica
+++ b/magic/Magdir/mathematica
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: mathematica,v 1.14 2021/11/07 16:27:36 christos Exp $
+# $File: mathematica,v 1.15 2022/10/31 13:22:26 christos Exp $
 # mathematica:  file(1) magic for mathematica files
 # "H. Nanosecond" <aldomel@ix.netcom.com>
 # Mathematica a multi-purpose math program
@@ -132,7 +132,7 @@
 >>>>0	ulelong		<53
 # skip tokens.dat and some Netwfw*.dat by check for valid imaginary flag value of MAT version 4
 >>>>>12	ulelong		<2
-# no misidentfied little endian MATrix example with "short" matrix name
+# no misidentified little endian MATrix example with "short" matrix name
 >>>>>>16	ulelong		<3
 >>>>>>>0	use	\^matlab4
 # little endian MATrix with "long" matrix name or some misidentified samples
--- a/magic/Magdir/meteorological
+++ b/magic/Magdir/meteorological
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: meteorological,v 1.2 2017/03/17 21:35:28 christos Exp $
+# $File: meteorological,v 1.4 2022/12/09 18:02:09 christos Exp $
 # rinex:  file(1) magic for RINEX files
 # http://igscb.jpl.nasa.gov/igscb/data/format/rinex210.txt
 # ftp://cddis.gsfc.nasa.gov/pub/reports/formats/rinex300.pdf
@@ -45,5 +45,9 @@
 
 # https://en.wikipedia.org/wiki/GRIB
 0	string	GRIB
->7	byte	=1	Gridded binary (GRIB) version 1
+>7	byte 	=1	Gridded binary (GRIB) version 1
+!:mime	application/x-grib
+!:ext	grb/grib
 >7	byte	=2	Gridded binary (GRIB) version 2
+!:mime	application/x-grib2
+!:ext	grb2/grib2
--- a/magic/Magdir/modem
+++ b/magic/Magdir/modem
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: modem,v 1.10 2021/04/26 15:56:00 christos Exp $
+# $File: modem,v 1.11 2022/10/19 20:15:16 christos Exp $
 # modem:  file(1) magic for modem programs
 #
 # From: Florian La Roche <florian@knorke.saar.de>
@@ -11,6 +11,7 @@
 # Summary: CCITT Group 3 Facsimile in "raw" form (i.e. no header).
 # Modified by: Joerg Jenderek
 # URL: https://de.wikipedia.org/wiki/Fax
+#	http://fileformats.archiveteam.org/wiki/CCITT_Group_3
 # Reference: https://web.archive.org/web/20020628195336/http://www.netnam.vn/unescocourse/computervision/104.htm
 # GRR: EOL of G3 is too general as it catches also TrueType fonts, Postscript PrinterFontMetric, others
 0	short		0x0100
@@ -32,7 +33,10 @@
 # skip MouseTrap/Mt.Defaults with file size 16 found on Golden Orchard Apple II CD Rom
 >>>>>>8		ubequad		!0x2e01010454010203
 # skip PICTUREH.SML found on Golden Orchard Apple II CD Rom
->>>>>>>8	ubequad		!0x5dee74ad1aa56394	raw G3 (Group 3) FAX, byte-padded
+>>>>>>>8	ubequad		!0x5dee74ad1aa56394
+# skip few (5/41) DEGAS mid-res bitmap (GEMINI01.PI2 GEMINI02.PI2 GEMINI03.PI2 CODE_RAM.PI2 TBX_DEMO.PI2)
+# with file size 32034
+>>>>>>>>-0	offset		!32034	raw G3 (Group 3) FAX, byte-padded
 # version 5.25 labeled the entry above "raw G3 data, byte-padded"
 !:mime	image/g3fax
 #!:apple	????TIFF
@@ -43,7 +47,9 @@
 # 16 0-bits near beginning like PicturePuzzler found on Golden Orchard Apple CD Rom
 >2	search/9	\0\0
 # maximal 7 0-bits for pixel sequences or 11 0-bits for EOL in G3
->2	default		x		raw G3 (Group 3) FAX
+>2	default		x
+# skip some (84/1246) MacBinary II/III (Cyberdog2.068k.smi.bin FileMakerPro4.img.bin Hypercard1.25.image.bin UsbStorage1.3.5.smi.bin) with "non random" numbers by versions values 81h/82h + 81h
+>>122	ubeshort&0xFcFf	!0x8081		raw G3 (Group 3) FAX
 # version 5.25 labeled the above entry as "raw G3 data"
 !:mime	image/g3fax
 !:ext	g3
--- a/magic/Magdir/msdos
+++ b/magic/Magdir/msdos
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: msdos,v 1.158 2022/09/07 11:17:31 christos Exp $
+# $File: msdos,v 1.163 2022/12/18 14:54:39 christos Exp $
 # msdos:  file(1) magic for MS-DOS files
 #
 
@@ -49,29 +49,127 @@
 #
 # Many of the compressed formats were extracted from IDARC 1.23 source code.
 #
+# e_magic
 0	string/b	MZ
-# All non-DOS EXE extensions have the relocation table more than 0x40 bytes into the file.
->0x18	leshort <0x40 MS-DOS executable
+#	TODO
+# FLT:	Syntrillium CoolEdit Filter		https://en.wikipedia.org/wiki/Adobe_Audition
+# FMX64:FileMaker Pro 64-bit plug-in		https://en.wikipedia.org/wiki/FileMaker
+# FMX:	FileMaker Pro 32-bit plug-in		https://en.wikipedia.org/wiki/FileMaker
+# FOD:	WIFE Font Driver
+# GAU:	MS Flight Simulator Gauge
+# IFS:	OS/2 Installable File System		https://en.wikipedia.org/wiki/OS/2
+# MEXW32:MATLAB Windows 32bit compiled function	https://en.wikipedia.org/wiki/MATLAB
+# MEXW64:MATLAB Windows 64bit compiled function	https://en.wikipedia.org/wiki/MATLAB
+# MLL:	Maya plug-in (generic)	       		http://en.wikipedia.org/wiki/Autodesk_Maya
+# PFL:	PhotoFilter plugin			http://photofiltre.free.fr
+# 8*:	PhotoShop plug-in (generic)		http://www.adobe.com/products/photoshop/main.html
+# PLG:	Aston Shell plugin			http://www.astonshell.com/
+# QLB:	Microsoft Basic Quick library		https://en.wikipedia.org/wiki/QuickBASIC
+# SKL:	WinLIFT skin				http://www.zapsolution.com/winlift/index.htm
+# TBK:	Asymetrix ToolBook application		http://www.toolbook.com
+# TBP:	The Bat! plugin	   			http://www.ritlabs.com
+# UPC:	Ultimate Paint Graphics Editor plugin	http://ultimatepaint.j-t-l.com
+# XFM:	Syntrillium Cool Edit Transform Effect	bad http://www.cooledit.com
+# XPL:	X-Plane plugin	      			http://www.xsquawkbox.net/xpsdk/
+# ZAP:	ZoneLabs Zone Alarm data		http://www.zonelabs.com
+#
+# NEXT LINES FOR DEBUGGING!
+# e_cblp; bytes on last page of file
+# e_cp; pages in file
+#>4		uleshort	x	\b, e_cp 0x%x
+# e_lfanew; file address of new exe header
+#>0x3c		ulelong		x	\b, e_lfanew 0x%x
+# e_lfarlc; address of relocation table
+#>0x18		uleshort	x	\b, e_lfarlc=0x%x
+# e_ovno; overlay number. If zero, this is the main executable foo
+#>0x1a		uleshort	!0	\b, e_ovno 0x%x
+#>0x1C		ubequad		!0	\b, e_res 0x%16.16llx
+# e_oemid; often 0
+#>0x24		uleshort	!0	\b, e_oemid 0x%x
+# e_oeminfo; typically zeroes, but 13Dh (WORDSTAR.CNV WPFT5.CNV) 143h (WRITWIN.CNV)
+# 1A3h (DBASE.CNV LOTUS123.CNV RFTDCA.CNV WORDDOS.CNV WORDMAC.CNV WORDWIN1.CNVXLBIFF.CNV)
+#>0x26		uleshort	!0	\b, e_oeminfo 0x%x
+#  e_res2; typically zeroes, but 000006006F082D2Ah SCSICFG.EXE 00009A0300007C03h de.exe
+# 0000CA0000000002h country.exe dosxmgr.exe 421E0A00421EA823h QMC.EXE
+#>0x28		ubequad		!0	\b, e_res2 0x%16.16llx
+# https://web.archive.org/web/20171116024937/http://www.ctyme.com/intr/rb-2939.htm#table1593
+# https://github.com/uxmal/reko/blob/master/src/ImageLoaders/MzExe/ExeImageLoader.cs
+# new exe header magic like: PE NE LE LX W3 W4
+# no examples found for ZM DL MP P2 P3
+#>(0x3c.l)	string		x	\b, at [0x3c] %.2s
+#>(0x3c.l)	ubelong		x	\b, at [0x3c] %#8.8x
+#>(0x3c.l+4)	ubelong		x	\b, at [0x3c+4] %#8.8x
+#
+# Most non-DOS MZ-executable extensions have the relocation table more than 0x40 bytes into the file.
+# http://www.mitec.cz/Downloads/EXE.zip/EXE64.exe	e_lfarlc=0x8ead
+# OS/2 ECS\INSTALL\DETECTEI\PCISCAN.EXE			e_lfarlc=0x1c
+# some EFI apps Shell_Full.efi ext4_x64_signed.efi	e_lfarlc=0
+# Icon library WORD60.ICL				e_lfarlc=0
+# Microsoft compiled help format 2.0 WINWORD.DEV.HXS	e_lfarlc=0
+>0x18	uleshort <0x40
+# check magic of new second header
+# NE executable with low e_lfarlc like: WORD60.ICL
+# ICL:	Icons Library 16-bit			http://fileformats.archiveteam.org/wiki/Icon_library
+>>(0x3c.l)	string	NE	Windows Icons Library 16-bit
+!:mime		image/x-ms-icl
+!:ext		icl
+# handle LX executable with low e_lfarlc like: PCISCAN.EXE
+>>(0x3c.l)	string	LX
+>>>(0x3c.l)	use		lx-executable
+# skip Portable Executable (PE) with low e_lfarlc here, because handled later
+# like: ext4_x64_signed.efi Shell_Full.efi WINWORD.DEV.HXS
+>>(0x3c.l)	string	PE
+# not New Executable (NE) and not PE with low e_lfarlc like:
+# MACCNV55.EXE WORK_RTF.EXE TELE200.EXE NDD.EXE iflash.exe
+>>(0x3c.l)	default	x	MS-DOS executable, MZ for MS-DOS
 !:mime	application/x-dosexec
 # Windows and later versions of DOS will allow .EXEs to be named with a .COM
 # extension, mostly for compatibility's sake.
+# like: EDIT.COM 4DOS.COM CMD8086.COM CMD-FR.COM SYSLINUX.COM
 # URL:		https://en.wikipedia.org/wiki/Personal_NetWare#VLM
 # Reference:	https://mark0.net/download/triddefs_xml.7z/defs/e/exe-vlm-msg.trid.xml
-!:ext	exe/com/vlm
+# also like: BGISRV.DRV
+!:ext	exe/com/vlm/drv
 # These traditional tests usually work but not always.  When test quality support is
 # implemented these can be turned on.
 #>>0x18	leshort	0x1c	(Borland compiler)
 #>>0x18	leshort	0x1e	(MS compiler)
 
 # Maybe it's a PE?
+# URL:		http://fileformats.archiveteam.org/wiki/Portable_Executable
+# Reference:	https://docs.microsoft.com/de-de/windows/win32/debug/pe-format
 >(0x3c.l)	string		PE\0\0	PE
-!:mime	application/x-dosexec
+!:mime	application/vnd.microsoft.portable-executable
+# https://docs.microsoft.com/de-de/windows/win32/debug/pe-format#characteristics
+# DLL Characteristics
+#>>(0x3c.l+22)	uleshort	x	\b, CHARACTERISTICS %#4.4x,
+# 0x0200~IMAGE_FILE_DEBUG_STRIPPED Debugging information is removed from the image file
+# 0x1000~IMAGE_FILE_SYSTEM The image file is a system file, not a user program. 
+# 0x2000~IMAGE_FILE_DLL The image file is a dynamic-link library (DLL)
 >>(0x3c.l+24)	leshort		0x010b	\b32 executable
+# https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#windows-subsystem
+#>>>(0x3c.l+92)	leshort		x	\b, SUBSYSTEM %u
 >>(0x3c.l+24)	leshort		0x020b	\b32+ executable
+#>>>(0x3c.l+92)	leshort		x	\b, SUBSYSTEM %u
 >>(0x3c.l+24)	leshort		0x0107	ROM image
 >>(0x3c.l+24)	default		x	Unknown PE signature
 >>>&0 		leshort		x	%#x
 >>(0x3c.l+22)	leshort&0x2000	>0	(DLL)
+# 0~IMAGE_SUBSYSTEM_UNKNOWN An unknown subsystem
+>>(0x3c.l+92)	leshort		0	(
+# Summary:	Microsoft compiled help *.HXS format 2.0
+# URL:		https://en.wikipedia.org/wiki/Microsoft_Help_2
+# Reference:	http://www.russotto.net/chm/itolitlsformat.html
+#		https://mark0.net/download/triddefs_xml.7z/defs/h/hxs.trid.xml
+# Note:		2 PE sections (.rsrc, .its) implies Microsoft compiled help format; the .its section contains the help content ITOLITLS
+#		verified by command like `pelook.exe -d WINWORD.HXS & pelook.exe -h WINWORD.HXS`
+>>>(0x3c.l+6)	uleshort	=2	\bMicrosoft compiled help format 2.0)
+!:ext	hxs
+# 3 PE sections (.text, .reloc, .rsrc) implies some Control Panel Item like: 
+# CPL:	Control Panel item for WINE 1.7.28	https://www.winehq.org/
+>>>(0x3c.l+6)	uleshort	!2	\bControl Panel Item)
+!:ext	cpl
+# 1~IMAGE_SUBSYSTEM_NATIVE device drivers and native Windows processes 
 >>(0x3c.l+92)	leshort		1
 # Native PEs include ntoskrnl.exe, hal.dll, smss.exe, autochk.exe, and all the
 # drivers in Windows/System32/drivers/*.sys.
@@ -79,6 +177,7 @@
 !:ext	dll/sys
 >>>(0x3c.l+22)	leshort&0x2000	0	(native)
 !:ext	exe/sys
+# 2~IMAGE_SUBSYSTEM_WINDOWS_GUI	The Windows graphical user interface (GUI) subsystem 
 >>(0x3c.l+92)	leshort		2
 >>>(0x3c.l+22)	leshort&0x2000	>0	(GUI)
 # These could probably be at least partially distinguished from one another by
@@ -94,21 +193,72 @@
 # Screen savers typically include code from the scrnsave.lib static library, but
 # that's not guaranteed.
 !:ext	exe/scr
+# 3~IMAGE_SUBSYSTEM_WINDOWS_CUI	The Windows character subsystem 
 >>(0x3c.l+92)	leshort		3
 >>>(0x3c.l+22)	leshort&0x2000	>0	(console)
 !:ext	dll/cpl/tlb/ocx/acm/ax/ime
 >>>(0x3c.l+22)	leshort&0x2000	0	(console)
 !:ext	exe/com
-# https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
->>(0x3c.l+92)	leshort		7	(POSIX)
->>(0x3c.l+92)	leshort		9	(Windows CE)
+# NO Windows Subsystem number 4!
+>>(0x3c.l+92)	leshort		4	(Unknown subsystem 4)
+# 5~IMAGE_SUBSYSTEM_OS2_CUI The OS/2 character subsystem 
+>>(0x3c.l+92)	leshort		5	(OS/2)
+# GRR: No examples found by Joerg Jenderek
+#!:ext	foo-exe-os2
+# NO Windows Subsystem number 6!
+>>(0x3c.l+92)	leshort		6	(Unknown subsystem 6)
+# 7~IMAGE_SUBSYSTEM_POSIX_CUI The Posix character subsystem 
+>>(0x3c.l+92)	leshort		7	(POSIX
+>>>(0x3c.l+22)	leshort&0x2000	>0	\b)
+# like: PSXDLL.DLL
+!:ext	dll
+>>>(0x3c.l+22)	leshort&0x2000	0	\b)
+# like: PAX.EXE
+!:ext	exe
+# 8~IMAGE_SUBSYSTEM_NATIVE_WINDOWS Native Win9x driver 
+>>(0x3c.l+92)	leshort		8	(Win9x)
+# GRR: No examples found by Joerg Jenderek
+#!:ext	foo-exe-win98
+# 9~IMAGE_SUBSYSTEM_WINDOWS_CE_GUI Windows CE
+>>(0x3c.l+92)	leshort		9	(Windows CE
+>>>(0x3c.l+22)	leshort&0x2000	>0	\b)
+# like: MCS9900Ce50.dll Mosiisr99x.dll TMCGPS.DLL
+!:ext	dll
+>>>(0x3c.l+22)	leshort&0x2000	0	\b)
+# like: NNGStart.exe navigator.exe
+!:ext	exe
+# 10~IMAGE_SUBSYSTEM_EFI_APPLICATION An Extensible Firmware Interface (EFI) application 
 >>(0x3c.l+92)	leshort		10	(EFI application)
+# like: bootmgfw.efi grub.efi gdisk_x64.efi Shell_Full.efi shim.efi syslinux.efi
+!:ext	efi
+# 11~IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER An EFI driver with boot services 
 >>(0x3c.l+92)	leshort		11	(EFI boot service driver)
+# like: ext2_x64_signed.efi Fat_x64.efi iso9660_x64_signed.efi
+!:ext	efi
 >>(0x3c.l+92)	leshort		12	(EFI runtime driver)
+# no sample found
+!:ext	efi
+# 13~IMAGE_SUBSYSTEM_EFI_ROM An EFI ROM image
 >>(0x3c.l+92)	leshort		13	(EFI ROM)
+# no sample found
+!:ext	efi
+# 14~IMAGE_SUBSYSTEM_XBOX XBOX 
 >>(0x3c.l+92)	leshort		14	(XBOX)
->>(0x3c.l+92)	leshort		15	(Windows boot application)
->>(0x3c.l+92)	default		x	(Unknown subsystem
+#!:ext	foo-xbox
+# NO Windows Subsystem number 15!
+>>(0x3c.l+92)	leshort		15	(Unknown subsystem 15)
+# 16~IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION Windows boot application
+>>(0x3c.l+92)	leshort		16	(Windows boot application
+>>>(0x3c.l+22)	leshort&0x2000	>0	\b)
+# like: bootvhd.dll bootuwf.dll hvloader.dll tcbloader.dll bootspaces.dll
+!:ext	dll
+>>>(0x3c.l+22)	leshort&0x2000	0	\b)
+# like: bootmgr.efi memtest.efi shellx64.efi memtest.exe winload.exe winresume.exe bootvhd.dll hvloader.dll
+!:ext	efi/exe
+# GRR: the next 2 lines are not executed!
+#>>(0x3c.l+92)	default		x	(Unknown subsystem
+#>>>&0		leshort		x	%#x)
+>>(0x3c.l+92)	leshort		>16	(Unknown subsystem
 >>>&0		leshort		x	%#x)
 >>(0x3c.l+4)	leshort		0x14c	Intel 80386
 >>(0x3c.l+4)	leshort		0x166	MIPS R4000
@@ -140,6 +290,7 @@
 >>(0x3c.l+4)	leshort		0x8664	x86-64
 >>(0x3c.l+4)	leshort		0xaa64	Aarch64
 >>(0x3c.l+4)	leshort		0xc0ee	MSIL
+# GRR: the next 2 lines are not executed!
 >>(0x3c.l+4)	default		x	Unknown processor type
 >>>&0		leshort		x	%#x
 >>(0x3c.l+22)	leshort&0x0200	>0	(stripped to external PDB)
@@ -176,33 +327,134 @@
 >>&(0x3c.l+0xf8)	search/0x100	_winzip_ \b, ZIP self-extracting archive (WinZip)
 >>&(0x3c.l+0xf8)	search/0x100	SharedD \b, Microsoft Installer self-extracting archive
 >>0x30			string		Inno \b, InnoSetup self-extracting archive
+# NumberOfSections; Normal Dynamic Link libraries have a few sections for code, data and resource etc.
+# PE used as container have less sections
+>>(0x3c.l+6)	leshort			>1	\b, %u sections
+# do not display for 1 section to get output like in version 5.43 and to keep output columns low
+#>>(0x3c.l+6)	leshort			=1	\b, %u section
 
 # If the relocation table is 0x40 or more bytes into the file, it's definitely
 # not a DOS EXE.
->0x18  leshort >0x3f
+>0x18	uleshort	>0x3f
 
 # Hmm, not a PE but the relocation table is too high for a traditional DOS exe,
 # must be one of the unusual subformats.
 >>(0x3c.l) string !PE\0\0 MS-DOS executable
-!:mime	application/x-dosexec
+#!:mime	application/x-dosexec
 
 >>(0x3c.l)		string		NE \b, NE
-!:mime	application/x-dosexec
+#!:mime	application/x-dosexec
+!:mime	application/x-ms-ne-executable
+# FOR DEBUGGING!
+# Reference:	https://wiki.osdev.org/NE
+# ProgFlags; Program flags, bitmapped
+#>>>(0x3c.l+0x0C)	ubyte		x	\b, ProgFlags 0x%2.2x
+# >>>(0x3c.l+0x0c)	ubyte&0x03	=0	\b, none
+# >>>(0x3c.l+0x0c)	ubyte&0x03	=1	\b, single shared
+# >>>(0x3c.l+0x0c)	ubyte&0x03	=2	\b, multiple
+# >>>(0x3c.l+0x0c)	ubyte&0x03	=3	\b, (null)
+# >>>(0x3c.l+0x0c)	ubyte		&0x04	\b, Global initialization
+# >>>(0x3c.l+0x0c)	ubyte		&0x08	\b, Protected mode only
+# >>>(0x3c.l+0x0c)	ubyte		&0x10	\b, 8086 instructions
+# >>>(0x3c.l+0x0c)	ubyte		&0x20	\b, 80286 instructions
+# >>>(0x3c.l+0x0c)	ubyte		&0x40	\b, 80386 instructions
+# >>>(0x3c.l+0x0c)	ubyte		&0x80	\b, 80x87 instructions
+# ApplFlags; Application flags, bitmapped
+# https://www.fileformat.info/format/exe/corion-ne.htm
+#>>>(0x3c.l+0x0D)	ubyte		x	\b, ApplFlags 0x%2.2x
+# Application type (bits 0-2); 1~Full screen (not aware of Windows/P.M. API)
+# 2~Compatible with Windows/P.M. API 3~Uses Windows/P.M. API
+#>>>(0x3c.l+0x0D)	ubyte&0x07	=1	\b, Full screen
+#>>>(0x3c.l+0x0D)	ubyte&0x07	=2	\b, Compatible with Windows/P.M. API
+#>>>(0x3c.l+0x0D)	ubyte&0x07	=3	\b, use Windows/P.M. API
+# bit 7; DLL or driver (SS:SP info invalid, CS:IP points at FAR init routine called with AX handle
+#>>>(0x3c.l+0x0D)	ubyte		&0x80	\b, DLL or driver
+# AutoDataSegIndex; automatic data segment index like: 0 2 3 22
+# zero if the SINGLEDATA and MULTIPLEDATA bits are cleared
+#>>>(0x3c.l+0x0e)	uleshort	x	\b, AutoDataSegIndex %u
+# InitHeapSize; intial local heap size like; 0 400h 1400h
+# zero if there is no local allocation
+#>>>(0x3c.l+0x10)	uleshort	!0	\b, InitHeapSize 0x%x
+# InitStackSize; inital stack size like: 0 10h A00h 7D0h A8Ch FA0h 1000h 1388h
+# 1400h (CBT) 1800h 2000h 2800h 2EE0h 2F3Ch 3258h 3E80h 4000h 4E20h 5000h 6000h
+# 6D60h 8000h 40000h
+# zero if the SS register value does not equal the DS register value
+#>>>(0x3c.l+0x12)	uleshort	!0	\b, InitStackSize 0x%x
+# EntryPoint; segment offset value of CS:IP like: 0 10000h 18A84h 11C1Ah 307F1h 
+#>>>(0x3c.l+0x14)	ulelong		!0 	\b, EntryPoint 0x%x
+# InitStack; specifies the segment offset value of stack pointer SS:SP
+# like: 0 20000h 160000h
+#>>>(0x3c.l+0x18)	ulelong		!0	\b, InitStack 0x%x
+# SegCount; number of segments in segment table like: 0 1 2 3 16h
+#>>>(0x3c.l+0x1C)	uleshort	x	\b, SegCount 0x%x
+# ModRefs; number of module references (DLLs) like; 0 1 3
+#>>>(0x3c.l+0x1E)	uleshort	!0	\b, ModRefs %u
+# NoResNamesTabSiz; size in bytes of non-resident names table
+# like: Bh 16h B4h B9h 2Ch 18Fh 16AAh
+#>>>(0x3c.l+0x20)	uleshort	x	\b, NoResNamesTabSiz 0x%x
+# SegTableOffset; offset of Segment table like: 40h
+#>>>(0x3c.l+0x22)	uleshort	!0x40	\b, SegTableOffset 0x%x
+# ResTableOffset; offset of resources table like: 40h 50h 58h F0h
+# 40h for most fonts likedos737.fon FMFONT.FOT but 60h for L1WBASE.FON
+#>>>(0x3c.l+0x24)	uleshort	x 	\b, ResTableOffset 0x%x
+# ResidNamTable; offset of resident names table
+# like: 58h 5Ch 60h 68h 74h 98h 2E3h 2E7h 2F0h
+#>>>(0x3c.l+0x26)	uleshort		x \b, ResidNamTable 0x%x
+# ImportNameTable; offset of imported names table (array of counted strings, terminated with string of length 00h)
+# like: 77h 7Eh 80h C6h A7h ACh 2F8h 3FFh
+#>>>(0x3c.l+0x2a)	uleshort	x	\b, ImportNameTable 0x%x
+# OffStartNonResTab; offset from start of file to non-resident names table
+# like: 110h 11Dh 19Bh 1A5h 3F5h 4C8h 4EEh D93h
+#>>>(0x3c.l+0x2c)	ulelong		x	\b, OffStartNonResTab 0x%x
+# MovEntryCount; number of movable entry points like: 0 4 5 6 16 17 24 312 355 446
+#>>>(0x3c.l+0x30)	uleshort	!0	\b, MovEntryCount %u
+# FileAlnSzShftCnt; log2 of the segment sector size; 4~16 0~9~512 (default)
+#>>>(0x3c.l+0x32)	uleshort	!9 	\b, FileAlnSzShftCnt %u
+# nResTabEntries; number of resource table entries like: 0 2
+#>>>(0x3c.l+0x34)	uleshort	!0	\b, nResTabEntries %u
+# targOS; Target OS; 0~unknown~OS/2 1.0 or MS Windows 1-2
+# OS/2 1.0 like: DTM.DLL SHELL11F.EXE HELPMSG.EXE CREATEDD.EXE
+# or Windows 1.03 - 2.1 like: MSDOSD.EXE KARTEI.EXE KALENDER.EXE
+#>>>(0x3c.l+0x36)	byte		x TARGOS %x
+>>>(0x3c.l+0x36)	byte		0 for OS/2 1.0 or MS Windows 1-2
 >>>(0x3c.l+0x36)	byte		1 for OS/2 1.x
 >>>(0x3c.l+0x36)	byte		2 for MS Windows 3.x
 >>>(0x3c.l+0x36)	byte		3 for MS-DOS
 >>>(0x3c.l+0x36)	byte		4 for Windows 386
 >>>(0x3c.l+0x36)	byte		5 for Borland Operating System Services
+# http://downloads.sourceforge.net/dfendreloaded/D-Fend-Reloaded-1.4.4.zip
+# D-Fend Reloaded/VirtualHD/FREEDOS/DPMILD32.EXE
+# GRR: WHAT OS is this?
+#>>>(0x3c.l+0x36)	byte		6 for TARGET SIX
+# https://en.wikipedia.org/wiki/Phar_Lap_(company)
+>>>(0x3c.l+0x36)	byte		0x81 for MS-DOS, Phar Lap DOS extender, OS/2
+# like: CVP7.EXE
+>>>(0x3c.l+0x36)	byte		0x82 for MS-DOS, Phar Lap DOS extender, Windows
 >>>(0x3c.l+0x36)	default		x
->>>>(0x3c.l+0x36)	byte		x (unknown OS %x)
->>>(0x3c.l+0x36)	byte		0x81 for MS-DOS, Phar Lap DOS extender
+>>>>(0x3c.l+0x36)	ubyte		x (unknown OS %#x)
+# expctwinver; expected Windows version (minor first) like:
+# 0.0~DTM.DLL 203.4~Windows 1.03 GDI.EXE 2.1~TTY.DRV 3.0~dos737.fon FMFONT.FOT THREED.VBX 3.10~GDI.EXE 4.0~(ME) VGAFULL.3GR
+>>>(0x3c.l+0x3F)	ubyte		x	(%u
+>>>(0x3c.l+0x3E)	ubyte		x	\b.%u)
+# OS2EXEFlags; other EXE flags
+# 0~Long filename support 1~2.x protected mode 4~2.x proportional fonts 8~Executable has gangload area
+#>>>(0x3c.l+0x37)	byte		!0	\b, OS2EXEFlags 0x%x
+# retThunkOffset; offset to return thunks or start of gangload area like: 0 34h 58h 246h 
+#>>>(0x3c.l+0x38)	uleshort	!0	\b, retThunkOffset 0x%x
+# segrefthunksoff; offset to segment reference thunks or size of gangload area
+# like: 0 33Eh 39Ah AEEh
+#>>>(0x3c.l+0x3A)	uleshort	!0	\b, segrefthunksoff 0x%x
+# mincodeswap; minimum code swap area size like 0 620Ch
+#>>>(0x3c.l+0x3C)	uleshort	!0 \b, mincodeswap 0x%x
 >>>(0x3c.l+0x0c)	leshort&0x8000	0x8000 (DLL or font)
 # DRV: Driver
 # 3GR: Grabber device driver
 # CPL: Control Panel Item
-# VBX: Visual Basic Extension
-# FON: Bitmap font
+# VBX: Visual Basic Extension		https://en.wikipedia.org/wiki/Visual_Basic
+# FON: Bitmap font			http://fileformats.archiveteam.org/wiki/FON
 # FOT: Font resource file
+# EXE: WINSPOOL.EXE USER.EXE krnl386.exe GDI.EXE
+# CNV: Microsoft Word text conversion	https://www.file-extensions.org/cnv-file-extension-microsoft-word-text-conversion-data
 !:ext	dll/drv/3gr/cpl/vbx/fon/fot
 >>>(0x3c.l+0x0c)	leshort&0x8000	0 (EXE)
 !:ext	exe/scr
@@ -228,8 +480,17 @@
 >>>&(&0x54.l-3)		string		arjsfx \b, ARJ self-extracting archive
 
 # MS Windows system file, supposedly a collection of LE executables
+# like vmm32.vxd WIN386.EXE
 >>(0x3c.l)		string		W3 \b, W3 for MS Windows
-!:mime	application/x-dosexec
+#!:mime	application/x-dosexec
+!:mime	application/x-ms-w3-executable
+!:ext	vxd/exe
+# W4 executable
+>>(0x3c.l)		string		W4 \b, W4 for MS Windows
+#!:mime	application/x-dosexec
+!:mime	application/x-ms-w4-executable
+# windows 98 VMM32.VXD
+!:ext	vxd
 
 >>(0x3c.l)		string		LE\0\0 \b, LE executable
 !:mime	application/x-dosexec
@@ -268,11 +529,19 @@
 !:ext	exe/com
 # header data too small for extended executable
 >2		long	!0
->>0x18		leshort <0x40
+>>0x18		uleshort <0x40
 >>>(4.s*512)	leshort !0x014c
 
 >>>>&(2.s-514)	string	!LE
->>>>>&-2	string	!BW \b, MZ for MS-DOS
+>>>>>&-2	string	!BW
+#>>>>>>(0x3c.l)	string		x	\b, 2ND MAGIC %.2s
+# but some LX executable appear here also like: PCISCAN.EXE
+>>>>>>(0x3c.l)	string	!LX
+# because Portable Executable (PE) already done skip many here like:
+# xcopy32.exe stinger64.exe WimUtil.exe
+# NO such DOS examples found and
+# DOS examples seems to be already handled by e_lfarlc <0x40 like: CMD8086.COM CMD-FR.COM
+>>>>>>>(0x3c.l)	string	!PE	\b, MZ for MS-DOS
 !:mime	application/x-dosexec
 >>>>&(2.s-514)	string	LE \b, LE
 >>>>>0x240	search/0x100	DOS/4G for MS-DOS, DOS4GW DOS extender
@@ -386,6 +655,7 @@
 >0x00	uleshort		x	executable
 #!:mime	application/x-msdownload
 !:mime	application/x-lx-executable
+!:ext	exe
 # byte order: 00h~little-endian non-zero=1~big-endian
 #>0x02	ubyte			=0		(little-endian)
 >0x02	ubyte			!0		(big-endian)
@@ -420,7 +690,7 @@
 >0x0a	leshort			3		for DOS
 # http://www.ctyme.com/intr/rb-2939.htm#Table1610
 # library by module type mask 00038000h (bits 15-17); 
-# 0h ~exectable Program module 
+# 0h ~executable Program module 
 >0x10	ulelong&0x00038000	=0x00000000	(program)
 #!:ext	exe
 # OSF_IS_DLL=8000h			~Library module (DLL)
@@ -602,11 +872,11 @@
 0       name    msdos-com
 # URL:		http://fileformats.archiveteam.org/wiki/DOS_executable_(.com)
 >0  byte        x               DOS executable (
-# DOS execuable with JuMP 16-bit instruction
+# DOS executable with JuMP 16-bit instruction
 >0	byte			=0xE9
 # check for probably nil padding til offset 64 of Lotus driver name
 >>56		quad		=0
-# check for "long" alpabetical Lotus driver name like:
+# check for "long" alphabetic Lotus driver name like:
 # Diablo "COMPAQ Text Display" "IBM Monochrome Display" "Plantronics ColorPlus"
 >>>24			regex	=^[A-Z][A-Za-z\040]{5,21}	\bLotus driver) %s
 !:mime				application/x-dosexec
@@ -616,7 +886,7 @@
 >>>24			default	x				\bCOM)
 !:mime				application/x-dosexec
 !:ext				com
-# DOS excutable with JuMP 16-bit and without nil padding
+# DOS executable with JuMP 16-bit and without nil padding
 >>56		quad		!0
 # https://wiki.syslinux.org/wiki/index.php?title=Doc/comboot
 # TODO: HOWTO distinguish COMboot from pure DOS executables?
@@ -781,7 +1051,7 @@
 >>1	default	x
 # look for interrupt instruction like in rem.com (DJGPP) LOADER.COM (DR-DOS 7.x)
 >>>3	search/118	\xCD
-# FOR DEBUGGING; possible hexadecimal interupt number like: 10~BANNER.COM 13~bcdw_cl.com 15~poweroff.com (Syslinux)
+# FOR DEBUGGING; possible hexadecimal interrupt number like: 10~BANNER.COM 13~bcdw_cl.com 15~poweroff.com (Syslinux)
 # 1A~BERNDPCI.COM 20~SETENHKB.COM 21~mostly 22~gfxboot.com (Syslinux) 2F~SHUTDOWN.COM (GEMSYS)
 #>>>>&0	ubyte	x			\b, INTERUPT %#x
 # few examples with interrupt 0x13 instruction
@@ -791,7 +1061,7 @@
 # skip Gpt.com Mbr.com (edk2-UDK2018 bootsector) described as "DOS/MBR boot sector" by ./filesystems
 # by check for assembler instructions: mov  es,ax ; mov  ax,07c0h ; mov ds,ax 
 >>>>>3	ubequad	!0x8ec0b8c0078ed88d
-# few COM exectables with interrupt 0x13 instruction like: Bootable CD Wizard executables bcdw_cl.com fdemuoff.com
+# few COM executables with interrupt 0x13 instruction like: Bootable CD Wizard executables bcdw_cl.com fdemuoff.com
 # http://bootcd.narod.ru/bcdw150z_en.zip
 >>>>>>0		use		msdos-com
 # few examples with interrupt 0x16 instruction like flashimg.img
@@ -806,7 +1076,7 @@
 #>>>>>&-1 ubyte	x			\b, INTERUPT %#x
 # like: LOADER.COM SETENHKB.COM banner.com copybs.com gif2raw.com poweroff.com rem.com
 >>>>>0		use		msdos-com
-# few COM executables without interupt instruction like RESTART.COM (DOS 7.10) REBOOT.COM
+# few COM executables without interrupt instruction like RESTART.COM (DOS 7.10) REBOOT.COM
 # or some EUC-KR text files or one Ulead Imaginfo thumbnail
 >>>3	default	x
 # FOR DEBUGGING; 2nd instruction like 0x50 (RESTART.COM) 0x8e (REBOOT.COM)
@@ -1575,6 +1845,12 @@
 >0x2c	default		x
 # look for 1st member name
 >>(16.l+16)	ubyte	x
+# From:		Joerg Jenderek
+# URL:		https://docs.microsoft.com/en-us/windows-hardware/drivers/install/building-device-metadata-packages
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/d/devicemetadata-ms.trid.xml
+>>>&-1	string 		PackageInfo.xml	\b, Device Metadata Package
+!:mime	application/vnd.ms-cab-compressed
+!:ext	devicemetadata-ms
 # https://en.wikipedia.org/wiki/SNP_file_format
 >>>&-1	string/c 	_accrpt_.snp	\b, Access report snapshot
 !:mime	application/msaccess
--- a/magic/Magdir/ole2compounddocs
+++ b/magic/Magdir/ole2compounddocs
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: ole2compounddocs,v 1.19 2022/09/11 20:52:40 christos Exp $
+# $File: ole2compounddocs,v 1.22 2022/12/09 15:56:56 christos Exp $
 # Microsoft OLE 2 Compound Documents : file(1) magic for Microsoft Structured
 # storage (https://en.wikipedia.org/wiki/Compound_File_Binary_Format)
 # Additional tests for OLE 2 Compound Documents should be under this recipe.
@@ -72,6 +72,7 @@
 #>67 	ubyte		x			\b, color %x
 # the DirIDs of the child nodes. Should both be -1 in the root storage entry
 #>68 	bequad		!0xffffffffffffffff	\b, DirIDs %llx
+# NEXT lines for DEBUGGING
 # second directory entry name like VisioDocument Control000 
 #>128	lestring16	x \b, 2nd %.20s
 # third directory entry like WordDocument
@@ -201,6 +202,18 @@
 !:ext	nfo
 #
 # From:		Joerg Jenderek
+# URL:		https://learn.microsoft.com/en-us/sysinternals/downloads/autoruns
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/a/arn-autoruns-v14.trid.xml
+# Note:		older versions til 13 about middle 2021 handled by ./windows
+#		called "Sysinternals Autoruns data (v14)" by TrID
+# second, third and fourth directory entry name like Header Items 0
+>>>>128 	lestring16	Header		: Microsoft sysinternals AutoRuns data, version 14
+#!:mime	application/x-ole-storage
+!:mime		application/x-ms-arn
+# like: MyHOSTNAME.arn
+!:ext		arn
+#
+# From:		Joerg Jenderek
 # URL:		https://en.wikipedia.org/wiki/Microsoft_Access
 # Reference:	http://mark0.net/download/triddefs_xml.7z/defs/m/mdz.trid.xml
 #		http://fileformats.archiveteam.org/wiki/Microsoft_Compound_File
@@ -305,62 +318,59 @@
 # THIS WORKS PARTLY!
 >>>>>>&0	indirect	x
 #	remaining null clsid
->>>>128 	default		x			: UNKNOWN
-# second directory entry name like VisioDocument Control000
->>>>>128	lestring16	x with names %.20s
-# third directory entry like WordDocument
->>>>>256	lestring16	x %.20s
-# forth
->>>>>384	lestring16	x %.20s
-!:mime	application/x-ole-storage
-# according to file version 5.41 with -e soft option
-#!:mime	application/CDFV2
-#!:ext	???
+>>>>128 	default		x
+>>>>>0 	use		ole2-unknown
 #	look for known clsid GUID
 # - Visio documents
 # URL:	http://fileformats.archiveteam.org/wiki/Visio
 #   Last update on 10/23/2006 by Lester Hightower, 07/20/2019 by Joerg Jenderek
->>88 	ubequad		0xc000000000000046	: Microsoft
->>>80 	ubequad		0x131a020000000000	Visio 2000-2002 Document, stencil or template
+>>88 	ubequad		0xc000000000000046
+>>>80 	ubequad		0x131a020000000000	: Microsoft Visio 2000-2002 Document, stencil or template
 !:mime	application/vnd.visio
 # VSD~Drawing VSS~Stencil VST~Template 
 !:ext	vsd/vss/vst
->>>80 	ubequad		0x141a020000000000	Visio 2003-2010 Document, stencil or template
+>>>80 	ubequad		0x141a020000000000	: Microsoft Visio 2003-2010 Document, stencil or template
 !:mime	application/vnd.visio
 !:ext	vsd/vss/vst
 #
 # URL:	http://fileformats.archiveteam.org/wiki/Windows_Installer
->>>80 	ubequad		0x84100c0000000000	Windows Installer Package
+#	https://en.wikipedia.org/wiki/Windows_Installer#ICE_validation
+# Update: Joerg Jenderek
+# Windows Installer Package *.MSI or validation module *.CUB
+>>>80 	ubequad		0x84100c0000000000	: Microsoft Windows Installer Package or validation module
 !:mime	application/x-msi
 #!:mime	application/x-ms-win-installer
-!:ext	msi
->>>80 	ubequad		0x86100c0000000000	Windows Installer Patch
+#	https://learn.microsoft.com/en-us/windows/win32/msi/internal-consistency-evaluators-ices
+# cub is used for validation module like: Vstalogo.cub XPlogo.cub darice.cub logo.cub mergemod.cub
+#!:mime	application/x-ms-cub
+!:ext	msi/cub
+>>>80 	ubequad		0x86100c0000000000	: Microsoft Windows Installer Patch
 # ??
 !:mime	application/x-wine-extension-msp
 #!:mime	application/x-ms-msp
 !:ext	msp
 #
 # URL:	http://fileformats.archiveteam.org/wiki/DOC
->>>80 	ubequad		0x0009020000000000	Word 6-95 document or template
+>>>80 	ubequad		0x0009020000000000	: Microsoft Word 6-95 document or template
 !:mime	application/msword
 # for template MSWDW8TN
 !:apple	MSWDWDBN
 !:ext	doc/dot
->>>80 	ubequad		0x0609020000000000	Word 97-2003 document or template
+>>>80 	ubequad		0x0609020000000000	: Microsoft Word 97-2003 document or template
 !:mime	application/msword
 !:apple	MSWDWDBN
 # dot for template; no extension on Macintosh
 !:ext	doc/dot/
 #
 # URL:	http://fileformats.archiveteam.org/wiki/Microsoft_Works_Word_Processor
->>>80 	ubequad		0x0213020000000000	Works 3-4 document or template
+>>>80 	ubequad		0x0213020000000000	: Microsoft Works 3-4 document or template
 !:mime	application/vnd.ms-works
 !:apple	????AWWP
 # ps for template	https://filext.com/file-extension/PS	bps for backup
 !:ext	wps/ps/bps
 #
 # URL:	http://fileformats.archiveteam.org/wiki/Microsoft_Works_Database
->>>80 	ubequad		0x0313020000000000	Works 3-4 database or template
+>>>80 	ubequad		0x0313020000000000	: Microsoft Works 3-4 database or template
 !:mime	application/vnd.ms-works-db
 # https://www.macdisk.com/macsigen.php
 !:apple	????AWDB
@@ -368,14 +378,14 @@
 !:ext	wdb/db/bdb
 #
 # URL:	https://en.wikipedia.org/wiki/Microsoft_Excel
->>>80 	ubequad		0x1008020000000000	Excel 5-95 worksheet, addin or template
+>>>80 	ubequad		0x1008020000000000	: Microsoft Excel 5-95 worksheet, addin or template
 !:mime	application/vnd.ms-excel
 # https://www.macdisk.com/macsigen.php
 !:apple	????XLS5
 # worksheet/addin/template/no extension on Macintosh
 !:ext	xls/xla/xlt/
 #
->>>80 	ubequad		0x2008020000000000	Excel 97-2003
+>>>80 	ubequad		0x2008020000000000	: Microsoft Excel 97-2003
 !:mime	application/vnd.ms-excel
 # https://www.macdisk.com/macsigen.php	XLS5 for Excel 5
 !:apple	????XLS9
@@ -391,23 +401,36 @@
 #!:ext	xls/xlt/
 #
 # URL:	http://fileformats.archiveteam.org/wiki/OLE2
->>>80 	ubequad		0x0b0d020000000000	Outlook 97-2003 item
-#>>>80 	ubequad		0x0b0d020000000000	Outlook 97-2003 Message
+>>>80 	ubequad		0x0b0d020000000000	: Microsoft Outlook 97-2003 item
+#>>>80 	ubequad		0x0b0d020000000000	: Microsoft Outlook 97-2003 Message
 #!:mime	application/vnd.ms-outlook
 !:mime	application/x-ms-msg
 !:ext	msg
 # URL:	https://wiki.fileformat.com/email/oft/
->>>80 	ubequad		0x46f0060000000000	Outlook 97-2003 item template
+>>>80 	ubequad		0x46f0060000000000	: Microsoft Outlook 97-2003 item template
 #!:mime	application/vnd.ms-outlook
 !:mime	application/x-ms-oft
 !:ext	oft
 #
 # URL:	http://fileformats.archiveteam.org/wiki/PPT
->>>80 	ubequad		0x5148040000000000	PowerPoint 4.0 presentation
+>>>80 	ubequad		0x5148040000000000	: Microsoft PowerPoint 4.0 presentation
 !:mime	application/vnd.ms-powerpoint
 # https://www.macdisk.com/macsigen.php
 !:apple	????PPT3
 !:ext	ppt
+# Summary:	"newer" Greenstreet Art drawing
+# From:		Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/GST_ART
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/a/art-gst-docfile.trid.xml
+# Note:		called like "Greenstreet Art drawing" by TrID
+# Note:		CONTENT stream contains binary part of older versions with phrase GST:ART at offset 16
+#		verified by Michal Mutl Structured Storage Viewer `SSView.exe BCARD2.ART`
+>>>80 	ubequad		0x602c020000000000	: Greenstreet Art drawing
+#!:mime	application/x-ole-storage
+!:mime	image/x-greenstreet-art
+!:ext	art
+>>>80 	default		x
+>>>>0 	use		ole2-unknown
 #??
 # URL:	http://www.checkfilename.com/view-details/Microsoft-Works/RespageIndex/0/sTab/2/
 >>88 	ubequad		0xa29a00aa004a1a72	: Microsoft
@@ -661,13 +684,28 @@
 #!:ext	max/chr
 # remaining non null clsid
 >>88 	default		x
-# GRR: check again for non null clsid because wrong when called by indirect directive
->>>88 	ubequad		!0			: UNKNOWN
+>>>0 	use		ole2-unknown
+# display information about directory for not detected CDF files
+0	name			ole2-unknown
+>80 	ubequad		x			: UNKNOWN
 # https://reposcope.com/mimetype/application/x-ole-storage
 !:mime	application/x-ole-storage
 # according to file version 5.41 with -e soft option
 #!:mime	application/CDFV2
 #!:ext	???
->>>>80 	ubequad		!0			\b, clsid %#16.16llx
->>>>88 	ubequad		x			\b%16.16llx
-
+>80 	ubequad		!0			\b, clsid %#16.16llx
+>>88 ubequad		x			\b%16.16llx
+# converted hexadecimal format to standard GUUID notation
+>>80	guid		x			{%s}
+# second directory entry name like VisioDocument Control000
+>128	lestring16	x with names %.20s
+# third directory entry like WordDocument Preview.dib
+>256	lestring16	x %.20s
+# forth like \005SummaryInformation
+>384	lestring16	x %.25s
+# 5th
+>512	lestring16	x %.10s
+# 6th
+>640	lestring16	x %.10s
+# 7th
+>768	lestring16	x %.10s
--- /dev/null
+++ b/magic/Magdir/playdate
@@ -0,0 +1,57 @@
+
+#------------------------------------------------------------------------------
+# $File: playdate,v 1.1 2022/11/04 13:34:48 christos Exp $
+#
+# Various native file formats for the Playdate portable video game console.
+#
+# These are unofficially documented at
+# https://github.com/jaames/playdate-reverse-engineering
+# 
+# The SDK is a source for many test files, and can be used to
+# create others. https://play.date/dev/
+
+
+# pdi: static image
+0	string	Playdate\ IMG	Playdate image data
+>12	belong&0x80	0x80	(compressed)
+>>20	lelong	x	%d x
+>>24	lelong	x	%d
+>12	belong&0x80	0x00	(uncompressed)
+>>16	leshort	x	%d x
+>>18	leshort	x	%d
+
+# pdt: multiple static images
+0	string	Playdate\ IMT	Playdate image data set
+>12	belong&0x80	0x80	(compressed)
+>>20	lelong	x	%d x
+>>24	lelong	x	%d,
+>>28	lelong	x	%d cells
+>12	belong&0x80	0x00	(uncompressed)
+>>20	lelong	x	tile grid %d x
+>>24	lelong	x	%d
+
+# pds: string tables
+0	string	Playdate\ STR	Playdate localization strings
+>12	belong&0x80	0x80	(compressed)
+>12	belong&0x80	0x00	(uncompressed)
+
+# pda: audio
+0	string	Playdate\ AUD	Playdate audio file
+>12	lelong&0xffffff	x	%d Hz,
+>15	byte	0	unsigned, 8-bit PCM, 1 channel
+>15	byte	1	unsigned, 8-bit PCM, 2 channel
+>15	byte	2	signed, 16-bit little-endian PCM, 1 channel
+>15	byte	3	signed, 16-bit little-endian PCM, 1 channel
+>15	byte	4	4-bit ADPCM, 1 channel
+>15	byte	5	4-bit ADPCM, 2 channel
+
+# pda: video
+0	string	Playdate\ VID	Playdate video file
+>24	leshort	x	%d x
+>26	leshort	x	%d,
+>16	leshort	x	%d frames,
+>20	lefloat x	%.2f FPS
+
+# pdz: executable package
+# Not a lot we can do, as it's a stream of entries with no summary information.
+0	string	Playdate\ PDZ	Playdate executable package
--- a/magic/Magdir/printer
+++ b/magic/Magdir/printer
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: printer,v 1.29 2019/04/19 00:42:27 christos Exp $
+# $File: printer,v 1.31 2022/12/18 14:50:43 christos Exp $
 # printer:  file(1) magic for printer-formatted files
 #
 
@@ -45,6 +45,8 @@
 #
 0	string		*PPD-Adobe:\x20	PPD file
 >&0	string		x		\b, version %s
+!:ext	ppd
+!:mime	application/vnd.cups-ppd
 
 # HP Printer Job Language
 0	string		\033%-12345X@PJL	HP Printer Job Language data
@@ -148,3 +150,82 @@
 # From: Paolo <oopla@users.sf.net>
 # Epson ESC/Page, ESC/PageColor
 0	string	\x1b\x01@EJL	Epson ESC/Page language printer data
+
+# Summary:	Hewlett-Packard Graphics Language
+# From:		Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/HP-GL
+#		https://en.wikipedia.org/wiki/HPGL
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/h/hpg.trid.xml
+# Note:		called "Hewlett-Packard Graphics Language" by TrID and
+#		"Hewlett Packard Graphics Language" by DROID via PUID x-fmt/293 and
+#		HPGL by XnView command `nconvert -info *`
+# initialize, start a plotting job 
+0	string	IN;
+>0		use		hpgl
+# fill.plt
+0	string	INPS
+>0		use		hpgl
+# http://ftp.funet.fi/index/graphics/packages/hpgl2ps/hpgl2ps.tar.Z/hpgl2ps/test1.hpgl 
+0	string	DF;
+>0		use		hpgl
+# http://ftp.funet.fi/index/graphics/packages/hpgl2ps/hpgl2ps.tar.Z/hpgl2ps/test3.hpgl 
+# Select Pen n
+0	string	SP
+>0		use		hpgl
+# charsize.hp pages.hp	set the scaling points (P1 and P2) to their default positions
+0	string	IP0
+>0		use		hpgl
+# ci.hp
+0	string	CO\040
+>0		use		hpgl
+# iw.hp 286x192.5_lh.hpg 286x192.5_lq.hpg
+0	string	PS\040
+>0		use		hpgl
+# thick.hp
+0	string	PS9
+>0		use		hpgl
+# ul.hp
+0	string	PS4
+>0		use		hpgl
+# la.hp
+0	string	BP
+>0		use		hpgl
+# miter.hp
+0	string	PA
+>0		use		hpgl
+# pw.hpg	number of pens x
+0	string	NP
+>0		use		hpgl
+# win_1.hp
+#0	string	\003INCA		WHAT_IS_THAT
+#>0		use		hpgl
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/h/hpgl2.trid.xml
+# Note:		called "Hewlett-Packard Graphics Language 2" by TrID
+0	string	\033%-1B		Hewlett-Packard Graphics Language 2
+!:mime	application/vnd.hp-HPGL
+# like: dt.plt
+!:ext	plt
+#!:ext	plt/gl2/hpg2/spl
+# remaining part after escsape sequnce
+>5	string	x			with "%-.10s"
+#	display Hewlett-Packard Graphics Language vector graphic information
+0	name				hpgl
+>0	string	x			Hewlett-Packard Graphics Language
+#!:mime	vector/x-hpgl
+# https://www.iana.org/assignments/media-types/application/vnd.hp-HPGL
+!:mime	application/vnd.hp-HPGL
+# no example with HPL suffix found
+!:ext	hpgl/hpg/hp/plt
+# like: "IN;" "DF;IN;LT;PU1000,1000;PD2000,10" "SP6;DI0,1;SR0.70,1.90;SC0,800,"
+# "CO Concentric circles drawn with different linewidths;"
+>0	string	x			\b, starting with "%-.54s"
+# continue but not for 1 long line without CR or LF
+>>&0	ubyte	<0x0E
+#>>&0	ubyte	<0x0E			TERMINATOR=%x
+# second line after 1 terminator character
+>>>&0	string	>\r			with "%-.10s"
+# next character again CR or LF
+>>>&0	ubyte	<0x0E
+#>>>&0	ubyte	<0x0E			2ND_CHARACTER=%x
+# second line after 2 terminator characters
+>>>>&0	string	>\r			with "%-.10s"
--- a/magic/Magdir/qt
+++ b/magic/Magdir/qt
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: qt,v 1.3 2019/04/19 00:42:27 christos Exp $
+# $File: qt,v 1.4 2022/11/11 14:50:23 christos Exp $
 # qt:  file(1) magic for Qt
 
 # https://doc.qt.io/qt-5/resources.html
@@ -17,3 +17,14 @@
 # src/corelib/kernel/qtranslator.cpp#L62
 0	string		\x3c\xb8\x64\x18\xca\xef\x9c\x95
 >8	string		\xcd\x21\x1c\xbf\x60\xa1\xbd\xdd	Qt Translation file
+
+
+# Qt V4 Javascript engine compiled unit
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/qt/qtdeclarative/blob/v6.4.0/src/qml/common/qv4compileddata_p.h
+0	string		qv4cdata	QV4 compiled unit
+!:ext	qmlc
+>8	ulelong		x		\b, version %d
+>12	byte		x		\b, Qt %d
+>13	byte		x		\b.%d
+>14	byte		x		\b.%d
--- /dev/null
+++ b/magic/Magdir/rust
@@ -0,0 +1,21 @@
+
+#------------------------------------------------------------------------------
+# $File: rust,v 1.2 2022/11/18 15:58:15 christos Exp $
+# Magic for Rust and related languages programs
+#
+
+# Rust compiler metadata
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/rust-lang/rust/blob/1.64.0/compiler/rustc_metadata/src/rmeta/mod.rs
+0	string		rust\x00\x00\x00
+>12	string		\014rustc\x20		Rust compiler metadata
+!:ext	rmeta
+>>7	byte		x			\b, version %d
+
+# Rust incremental compilation metadata
+# From: Alexandre Iooss <erdnaxe@crans.org>
+# URL: https://github.com/rust-lang/rust/blob/1.64.0/compiler/rustc_incremental/src/persist/file_format.rs
+0	string		RSIC
+>4	uleshort	=0			Rust incremental compilation metadata
+!:ext	bin
+>>6	pstring		x			\b, rustc %s
--- a/magic/Magdir/sendmail
+++ b/magic/Magdir/sendmail
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: sendmail,v 1.11 2019/04/19 00:42:27 christos Exp $
+# $File: sendmail,v 1.12 2022/10/31 13:22:26 christos Exp $
 # sendmail:  file(1) magic for sendmail config files
 #
 # XXX - byte order?
@@ -13,7 +13,7 @@
 # - version \330jK\354
 0	byte	046
 # https://www.sendmail.com/sm/open_source/docs/older_release_notes/
-# freezed configuration file (dbm format?) created from sendmal.cf with -bz
+# freezed configuration file (dbm format?) created from sendmail.cf with -bz
 # by older sendmail. til version 8.6 support for frozen configuration files is removed
 # valid version numbers look like "7.14.4" and should be similar to output of commands
 # "sendmail -d0 -bt < /dev/null |grep -i Version" or "egrep '^DZ' /etc/sendmail.cf"
--- a/magic/Magdir/sniffer
+++ b/magic/Magdir/sniffer
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: sniffer,v 1.32 2022/07/30 16:46:56 christos Exp $
+# $File: sniffer,v 1.34 2022/12/14 18:27:36 christos Exp $
 # sniffer:  file(1) magic for packet capture files
 #
 # From: guy@alum.mit.edu (Guy Harris)
@@ -327,14 +327,79 @@
 
 #
 # Novell LANalyzer capture files.
-#
-0	leshort		0x1001		Novell LANalyzer capture file
-0	leshort		0x1007		Novell LANalyzer capture file
+# URL:		http://www.blacksheepnetworks.com/security/info/nw/lan/trace.txt
+# Reference:	https://github.com/wireshark/wireshark/blob/master/wiretap/lanalyzer.c
+# Update:	Joerg Jenderek
+# 
+# regular trace header record (RT_HeaderRegular)
+0	leshort		0x1001
+# GRR: line above is too generic because it matches Commodore Plus/4 BASIC V3.5
+# and VIC-20 BASIC V2 program
+# skip many Commodore Basic program (Microzodiac.prg Minefield.prg Vic-tac-toe.prg breakvic_joy.prg)
+# with invalid second record type 0 instead of "Trace receive channel name record"
+>(2.s+4)	leshort	=0x1006h
+>>0	use	novell-lanalyzer
+# cyclic trace header record (RT_HeaderCyclic)
+0	leshort		0x1007
+>0	use	novell-lanalyzer
+0	name	novell-lanalyzer
+>0	leshort		x		Novell LANalyzer capture file
+# https://reposcope.com/mimetype/application/x-lanalyzer
+!:mime	application/x-lanalyzer
+# maybe also TR2 .. TR9 TRA .. TRZ
+!:ext	tr1
+# version like: 1.5
+>4		ubyte	x		\b, version %u
+# minor version; one byte identifying the trace file minor version number
+>5		ubyte	x		\b.%u
+# Trace header record type like: 1001~regular or 1007~cyclic
+>0	leshort		!0x1001		\b, record type %4.4x
+# record_length[2] is the length of the data part of 1st reorcd (without "type" and "length" fields) like: 4Ch
+>2		leshort	x		\b, record length %#x
+# second record type like: 1006h~Trace receive channel name record
+>(2.s+4)	leshort	!0x1006h	\b, 2nd record type %#4.4x
+>(2.s+6)	leshort	x		\b, 2nd record length %#x
+# each channel name is a null-terminated, eight-byte ASCII string like: Channel1
+>(2.s+8)	string	x		\b, names %.9s
+# 2nd channel name like: Channel2
+>(2.s+17)	string	x		%.9s ...
 
 #
 # HP-UX "nettl" capture files.
-#
+# URL:		https://nixdoc.net/man-pages/HP-UX/man1m/nettl.1m.html
+# Reference:	https://github.com/wireshark/wireshark/blob/master/wiretap/nettl.c
+# Update:	Joerg Jenderek
+# Note:		Wireshark fills "meta information header fields" with "dummy" values 
+# nettl_magic_hpux9[12]; for HP-UX 9.x not tested
+0	string		\x00\x00\x00\x01\x00\x00\x00\x00\x00\x07\xD0\x00	HP/UX 9.x nettl capture file
+!:mime	application/x-nettl
+!:ext	trc0/trc1
+# nettl_magic_hpux10[12]; for HP-UX 10.x and 11.x
 0	string		\x54\x52\x00\x64\x00	HP/UX nettl capture file
+# https://reposcope.com/mimetype/application/x-nettl
+!:mime	application/x-nettl
+# maybe also TRC000 TRC001 TRC002 ...
+!:ext	trc0/trc1
+# file_name[56]; maybe also like /tmp/raw.tr.TRC000
+>12	string		!/tmp/wireshark.TRC000
+>>12	string		x			"%-.56s"
+# tz[20]; like UTC
+>68	string		!UTC			\b, tz
+>>68	string		x			%-.20s
+# host_name[9];
+>88	string		>\0			\b, host %-.9s
+# os_vers[9]; like B.11.11
+>97	string		!B.11.11		\b, os
+>>97	string		x			%-.9s
+# os_v; like 55h
+>>106	ubyte		x			(%#x)
+# xxa[8]; like 0
+>107	ubequad		!0			\b, xxa=%#16.16llx
+# model[11] like: 9000/800
+>115	string		!9000/800		\b, model
+>>115	string		x			%-.11s
+# unknown; probably just padding to 128 bytes like: 0406h
+>126	ubeshort	!0x0406h		\b, at 126 %#4.4x
 
 #
 # RADCOM WAN/LAN Analyzer capture files.
--- a/magic/Magdir/softquad
+++ b/magic/Magdir/softquad
@@ -1,7 +1,8 @@
 
 #------------------------------------------------------------------------------
-# $File: softquad,v 1.13 2009/09/19 16:28:12 christos Exp $
+# $File: softquad,v 1.14 2022/10/28 17:19:54 christos Exp $
 # softquad:  file(1) magic for SoftQuad Publishing Software
+# URL:		https://en.wikipedia.org/wiki/SoftQuad_Software
 #
 # Author/Editor and RulesBuilder
 #
@@ -17,8 +18,10 @@
 0	short		0xc0da		Compiled PSI (v2) data
 >3	string		>\0		(%s)
 # Binary sqtroff font/desc files...
-0	short		0125252		SoftQuad DESC or font file binary
->2	short		>0		- version %d
+# GRR: the line below is also true for 5View capture file handled by ./sniffer
+0	short		0125252
+# skip 5View capture file with "invalid" version AAAAh
+>2	short		>0		SoftQuad DESC or font file binary - version %d
 # Bitmaps...
 0	search/1	SQ\ BITMAP1	SoftQuad Raster Format text
 #0	string		SQ\ BITMAP2	SoftQuad Raster Format data
--- a/magic/Magdir/sysex
+++ b/magic/Magdir/sysex
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------
-# $File: sysex,v 1.11 2022/01/17 17:16:51 christos Exp $
+# $File: sysex,v 1.12 2022/10/31 13:22:26 christos Exp $
 # sysex: file(1) magic for MIDI sysex files
 #
 # GRR: original 1 byte test at offset was too general as it catches also many FATs of DOS filesystems
@@ -10,8 +10,8 @@
 0	ubeshort&0xFF80		0xF000
 # MIDI System Exclusive (SysEx) messages (strength=50) after Microsoft Visual C library (strength=70)
 #!:strength +0
-# skip Microsoft Visual C library with page size 16 misidentifed as ADA and
-# page size 32 misidentifed as Inventronics by looking for terminating End Of eXclusive byte (EOX)
+# skip Microsoft Visual C library with page size 16 misidentified as ADA and
+# page size 32 misidentified as Inventronics by looking for terminating End Of eXclusive byte (EOX)
 >2		search/12	\xF7
 >>0	use	midi-sysex
 #	display information about MIDI System Exclusive (SysEx) messages
--- a/magic/Magdir/terminfo
+++ b/magic/Magdir/terminfo
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: terminfo,v 1.12 2021/02/23 00:51:10 christos Exp $
+# $File: terminfo,v 1.13 2022/11/21 22:25:37 christos Exp $
 # terminfo:  file(1) magic for terminfo
 #
 # URL: https://invisible-island.net/ncurses/man/term.5.html
@@ -37,6 +37,7 @@
 # AIX and HPUX use the SVr4 big-endian format
 # Solaris uses the SVr3 formats (sparc and x86 differ endian-ness)
 0	beshort		0433 		SVr2 curses screen image, big-endian
+# GRR: line below too general as it catches Commodore C128 program (crc32.prg XLINK.PRG) with start address 1C01h handled by ./c64
 0	beshort		0434		SVr3 curses screen image, big-endian
 0	beshort		0435		SVr4 curses screen image, big-endian
 #
--- a/magic/Magdir/tex
+++ b/magic/Magdir/tex
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: tex,v 1.21 2019/04/19 00:42:27 christos Exp $
+# $File: tex,v 1.22 2022/12/21 16:50:04 christos Exp $
 # tex:  file(1) magic for TeX files
 #
 # XXX - needs byte-endian stuff (big-endian and little-endian DVI?)
@@ -10,13 +10,15 @@
 # Although we may know the offset of certain text fields in TeX DVI
 # and font files, we can't use them reliably because they are not
 # zero terminated. [but we do anyway, christos]
-0	string		\367\002	TeX DVI file
+0	string		\367\002
+>(14.b+15)	string	\213
+>>14	pstring		>\0		TeX DVI file (%s)
 !:mime	application/x-dvi
->16	string		>\0		(%s)
 0	string		\367\203	TeX generic font data
 0	string		\367\131	TeX packed font data
 >3	string		>\0		(%s)
-0	string		\367\312	TeX virtual font data
+0	string		\367\312
+>(2.b+11)	string	\363	TeX virtual font data
 0	search/1	This\ is\ TeX,	TeX transcript text
 0	search/1	This\ is\ METAFONT,	METAFONT transcript text
 
--- a/magic/Magdir/uterus
+++ b/magic/Magdir/uterus
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: uterus,v 1.3 2014/04/30 21:41:02 christos Exp $
+# $File: uterus,v 1.4 2022/10/31 13:22:26 christos Exp $
 # file(1) magic for uterus files
 # http://freecode.com/projects/uterus
 #
@@ -11,6 +11,6 @@
 >7	byte		x	\b%c
 >8	string		\<\>	\b, big-endian
 >>16	belong		>0	\b, slut size %u
->8	string		\>\<	\b, litte-endian
+>8	string		\>\<	\b, little-endian
 >>16	lelong		>0	\b, slut size %u
 >10	byte		&8	\b, compressed
--- a/magic/Magdir/varied.script
+++ b/magic/Magdir/varied.script
@@ -1,59 +1,21 @@
 #------------------------------------------------------------------------------
-# $File: varied.script,v 1.13 2019/10/11 14:35:29 christos Exp $
+# $File: varied.script,v 1.15 2022/10/18 13:01:30 christos Exp $
 # varied.script:  file(1) magic for various interpreter scripts
 
-0	string/t		#!\ /			a
->3	string		>\0			%s script text executable
-!:strength / 2
+0	string/wt	#!\ 	a
+>&-1	string/T	x	%s script text executable
+!:strength / 3
+
+0	string/wb	#!\ 	a
+>&-1	string/T	x	%s script executable (binary data)
+!:strength / 3
 
-0	string/b		#!\ /			a
->3	string		>\0			%s script executable (binary data)
-!:strength / 2
-
-0	string/t		#!\t/			a
->3	string		>\0			%s script text executable
-!:strength / 2
-
-0	string/b		#!\t/			a
->3	string		>\0			%s script executable (binary data)
-!:strength / 2
-
-0	string/t		#!/			a
->2	string		>\0			%s script text executable
-!:strength / 2
-
-0	string/b		#!/			a
->2	string		>\0			%s script executable (binary data)
-!:strength / 2
-
-0	string/t		#!\ 			script text executable
->3	string		>\0			for %s
-!:strength / 2
-
-0	string/b		#!\ 			script executable
->3	string		>\0			for %s (binary data)
-!:strength / 2
 
 # using env
-0	string/t	#!/usr/bin/env		a
->15	string/t	>\0			%s script text executable
-!:strength / 10
-
-0	string/b	#!/usr/bin/env		a
->15	string/b	>\0			%s script executable (binary data)
-!:strength / 10
-
-0	string/t	#!\ /usr/bin/env	a
->16	string/t	>\0			%s script text executable
-!:strength / 10
-
-0	string/b	#!\ /usr/bin/env	a
->16	string/b	>\0			%s script executable (binary data)
-!:strength / 10
-
-# From: arno <arenevier@fdn.fr>
-# mozilla xpconnect typelib
-# see https://www.mozilla.org/scriptable/typelib_file.html
-0	string 		XPCOM\nTypeLib\r\n\032		XPConnect Typelib
->0x10  byte        x       version %d
->>0x11 byte        x      \b.%d
+0	string/wt	#!\ /usr/bin/env		a
+>15	string/T	>\0			%s script text executable
+!:strength / 6
+
+0	string/wb	#!\ /usr/bin/env		a
+>15	string/T	>\0			%s script executable (binary data)
+!:strength / 6
--- a/magic/Magdir/web
+++ b/magic/Magdir/web
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: web,v 1.1 2020/05/17 19:14:28 christos Exp $
+# $File: web,v 1.2 2022/10/29 16:02:37 christos Exp $
 
 # http://www.rdfhdt.org/
 # From Christoph Biedl
@@ -10,3 +10,9 @@
 0	string	$HDT\x01 HDT file (binary compressed indexed RDF triples) type 1
 !:mime application/vnd.hdt
 !:ext hdt
+
+0	string		[Adblock\040Plus	Adblock Plus
+>&1	regex		[0-9.]+			%s
+>1	string		x			rules file
+>10	search/100	Version:
+>>&1	regex		[0-9]+			\b, version %s
--- a/magic/Magdir/windows
+++ b/magic/Magdir/windows
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: windows,v 1.46 2022/07/02 17:46:09 christos Exp $
+# $File: windows,v 1.50 2022/11/30 20:24:43 christos Exp $
 # windows:  file(1) magic for Microsoft Windows
 #
 # This file is mainly reserved for files where programs
@@ -115,10 +115,23 @@
 
 
 # Summary: Vista Event Log
-# Extension: .evtx
 # Created by: Andreas Schuster (https://computer.forensikblog.de/)
-# Reference (1): https://computer.forensikblog.de/en/2007/05/some_magic.html
-0	string		ElfFile\0	MS Windows Vista Event Log
+# Update:	Joerg Jenderek
+# URL:		https://github.com/libyal/libevtx/blob/main/documentation/Windows%20XML%20Event%20Log%20(EVTX).asciidoc
+# Reference (1): https://web.archive.org/web/20110803085000/
+#		https://computer.forensikblog.de/en/2007/05/some_magic.html
+#		http://mark0.net/download/triddefs_xml.7z/defs/e/evtx.trid.xml
+# Note:		called "Vista Event Log" by TrID and "Event Log" by Windows
+# 		verified partly by `wevtutil.exe gli /lf:true dumpfile.evtx`
+0	string		ElfFile\0	MS Windows
+#!:mime		application/octet-stream
+!:mime		application/x-ms-evtx
+!:ext		evtx
+# Major+Minor format version: 3.1~Vista and later 3.2~Windows 10 (2004) and later 
+>0x24	ulelong		=0x00030001	Vista-8.1 Event Log
+>0x24	ulelong		!0x00030001	10-11 Event Log, version 
+>>0x26	uleshort	x		%u
+>>0x24	uleshort	x		\b.%u
 >0x2a	leshort		x		\b, %d chunks
 >>0x10	lelong		x		\b (no. %d in use)
 >0x18	lelong		>1		\b, next record no. %d
@@ -126,6 +139,32 @@
 >0x78	lelong		&1		\b, DIRTY
 >0x78	lelong		&2		\b, FULL
 
+# Summary:	Windows Event Trace Log
+# From:		Joerg Jenderek
+# URL:		http://fileformats.archiveteam.org/wiki/ETL
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/e/etl.trid.xml
+#		https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/etw/tracelog/trace_logfile_header.htm
+# Note:		called "Window tracing/diagnostic binary log" by TrID
+# 		verified by `tracerpt.EXE Wifi.etl -of EVTX`
+#		and by etl-parser `etl2xml --input AMSITrace.etl --output AMSITrace.xml`
+# Every ETL file begins with a WMI_BUFFER_HEADER, a SYSTEM_TRACE_HEADER and a TRACE_LOGFILE_HEADER
+0	ubyte			0
+# look for corresponding encoded as UTF-16 file name extension like in: boot_BASE+CSWITCH_1.etl
+>0	search/0x699087/b	.\0e\0t\0l\0\0\0
+# GRR: line above only works if in ../../src/file.h FILE_BYTES_MAX is raised above 699086h (6,59 MiB)
+>>0	use			trace-etl
+# display information of Windows Performance Analyzer Trace File (file name)
+0	name		trace-etl
+>0	ubyte			x		Windows Event Trace Log
+#!:mime		application/x-ms-etl
+# http://extension.nirsoft.net/etl
+!:mime		application/etl
+!:ext		etl
+# look for DOS drive letter part of log file name like: PhotosAppTracing_startedInBGMode.etl
+>0	search/0x2b4/sb	:\0\x5c\0	
+# like: "c:\Windows\Logs\NetSetup\service.0.etl" "C:\Windows\System32\LogFiles\WMI\Wifi.etl"
+>>&-2	lestring16		x		"%s"
+
 # Summary: Windows System Deployment Image
 # Created by: Joerg Jenderek
 # URL: http://en.wikipedia.org/wiki/System_Deployment_Image
@@ -752,6 +791,27 @@
 # like: 12510866.CPX 
 !:ext	cpx
 # From:		Joerg Jenderek
+# URL:		https://en.wikipedia.org/wiki/File_Explorer
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/s/scf-exp.trid.xml,scf-exp-old.trid.xml
+# Note:		called "Windows Explorer Command Shell File" by TrID and "File Explorer Command" by Windows via SHCmdFile
+>>&0	regex/c		\^Shell]\r\n					Windows Explorer Shell Command File
+#!:mime	text/plain
+!:mime	text/x-ms-scf
+# like: channels.scf desktop.scf explorer.scf "Desktop anzeigen.scf"
+!:ext	scf
+# look for icon file directive maybe pointing to malicious file
+>>>1		search/128	IconFile=				\b, icon
+>>>>&0		string		x					"%s"
+# From:		Joerg Jenderek
+# URL:		http://en.wikipedia.org/wiki/VIA_Technologies
+# Reference:	http://mark0.net/download/triddefs_xml.7z/defs/s/scf-via.trid.xml
+# Note:		called "VIA setup configuration file" by TrID
+>>&0	regex/c		\^SCF]\r\n					VIA setup configuration
+#!:mime	text/plain
+!:mime	text/x-via-scf
+# like: SETUP.SCF
+!:ext	scf
+# From:		Joerg Jenderek
 # URL:		https://en.wikipedia.org/wiki/InstallShield
 # Reference:	http://mark0.net/download/triddefs_xml.7z/defs/l/lid-is.trid.xml
 # Note:		contain also 3 keywords like: count Default key0
@@ -871,21 +931,24 @@
 >>>2		uleshort	<3
 # look for colon in WinDirPath after PNF header
 #>>>>0x59	search/18	:
->>>>0	use	PreCompiledInf
+# skip few Adobe Photoshop Color swatch ("Mac OS.aco" TRUMATCH-Farben.aco Windows.aco) and some
+# Targa image (money-256.tga XING_B_UCM8.tga x-fmt-367-signature-id-604.tga) with "invalid low section name" \0
+>>>>(20.l)	ubelong		>0x40004000
+>>>>>0	use	PreCompiledInf
 0	name	PreCompiledInf
 >0		uleshort	x	Windows Precompiled iNF
 !:mime	application/x-pnf
 !:ext	pnf
 # major version 1 for older Windows like XP and 3 since about Windows Vista
-# 101h~98-XP; 301h~Windows Vista-7 ; 302h~Windows 10 14393; 303h~Windows 10 18362
+# 101h~95-XP; 301h~Windows Vista-7 ; 302h~Windows 10 14393; 303h~Windows 10 18362-Windows11
 >1		ubyte		x		\b, version %u
 >0		ubyte		x		\b.%u
 >0		uleshort	=0x0101		(Windows
->>4	ulelong&0x00000001	!0x00000001	98)
+>>4	ulelong&0x00000001	!0x00000001	95-98)
 >>4	ulelong&0x00000001	=0x00000001	XP)
 >0		uleshort	=0x0301		(Windows Vista-8.1)
 >0		uleshort	=0x0302		(Windows 10 older)
->0		uleshort	=0x0303		(Windows 10)
+>0		uleshort	=0x0303		(Windows 10-11)
 # 1 ,2 (windows 98 SE)
 >2		uleshort	!2		\b, InfStyle %u
 #	PNF_FLAG_IS_UNICODE		0x00000001
@@ -927,7 +990,7 @@
 >>(20.l)	string		x		"%s"
 # FILETIME is number of 100-nanosecond intervals since 1 January 1601
 #>24		ulequad		x		\b, InfVersionLastWriteTime %16.16llx
-#>24		foodate-0xbar	x		\b, InfVersionLastWriteTime %s
+>24		qwdate		x		\b, InfVersionLastWriteTime %s
 # for Windows 98, XP
 >0		uleshort	<0x0102
 # only found values lower 0x00ffFFff
@@ -965,6 +1028,7 @@
 >>>>>(72.l)	string		x		OsLoaderPath "%s"
 # 1fdh
 #>>>76		uleshort	x		\b, StringTableHashBucketCount %#x
+# https://docs.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a
 # only 407h found
 >>>78		uleshort	!0x409		\b, LanguageID %x
 #>>>78		uleshort	=0x409		\b, LanguageID %x
@@ -1342,7 +1406,7 @@
 # 5000010021083f00 50000100b0335600 50000100cbfdf800 50000100dfbc4700
 #>4	ubequad		x		\b, at 4 %#16.16llx
 # copyright text like:	"Stirling Technologies, Inc.  (c) 1990-1994"
-#			"InstallSHIELD Software Coporation  (c) 1990-1997"
+#			"InstallSHIELD Software Corporation  (c) 1990-1997"
 >13	pstring/h	x		"%s"
 # look for specific ASCII variable names
 >1	search/0x121/s	SRCDIR	\b, variable names:
--- a/magic/Magdir/wordprocessors
+++ b/magic/Magdir/wordprocessors
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: wordprocessors,v 1.31 2022/08/31 08:00:53 christos Exp $
+# $File: wordprocessors,v 1.32 2022/10/31 13:22:26 christos Exp $
 # wordprocessors:  file(1) magic fo word processors.
 #
 ####### PWP file format used on Smith Corona Personal Word Processors:
@@ -430,7 +430,7 @@
 >110	uleshort/256	=0			document
 # https://www.macdisk.com/macsigen.php
 !:apple	ALB3ALD3
-# PT3 for template and no example for PageMaker document/publiction with PM3 extension
+# PT3 for template and no example for PageMaker document/publication with PM3 extension
 !:ext	pm3/pt3
 >110	uleshort/256	=4			document
 !:apple	ALD4ALB4
--- a/magic/Magdir/xenix
+++ b/magic/Magdir/xenix
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: xenix,v 1.14 2021/04/26 15:56:00 christos Exp $
+# $File: xenix,v 1.15 2022/10/19 20:15:16 christos Exp $
 # xenix:  file(1) magic for Microsoft Xenix
 #
 # "Middle model" stuff, and "Xenix 8086 relocatable or 80286 small
@@ -28,20 +28,23 @@
 # skip examples like Xtable.Data FRACTAL.GEN SHR.VIEW by looking for positive string length
 >>>3	ubyte		>0
 # skip examples like OMBRE.6 with "UUUUUU" name by looking for valid high second record type
->>>>(1.s+3)	ubyte	>0x6D	8086 relocatable (Microsoft)
+>>>>(1.s+3)	ubyte	>0x6D
+# skip few Atari DEGAS bitmap TPDEMO.PC2 RECIPE.PC2 with invalid "high" second record type FEh FFh
+>>>>>(1.s+3)	ubyte	<0xF2	8086 relocatable (Microsoft)
 #!:mime	application/octet-stream
 !:mime	application/x-object
 !:ext	obj/o/a
 # T-module name often source name like "hello.c" or "jmppm32.asm" in JMPPM32.OBJ or
 # "kbhit" in KBHITS.OBJ or "CAUSEWAY_KERNAL" in CWAPI.OBJ
->>>>>3	pstring		x		\b, "%s"
+>>>>>>3	pstring		x		\b, "%s"
 # data length probably lower 256 according to TrID obj_omf.trid.xml
->>>>>1	uleshort	x		\b, 1st record data length %u
+>>>>>>1	uleshort	x		\b, 1st record data length %u
 # checksum
-#>>>>>(3.b+4)	ubyte	x		\b, checksum %#2.2x
+#>>>>>>(3.b+4)	ubyte	x		\b, checksum %#2.2x
 # second recordtype: 96h~LNAMES 88h~COMENT 8CH~EXTDEF
->>>>>(1.s+3)	ubyte	x		\b, 2nd record type %#x
->>>>>(1.s+4)	uleshort x		\b, 2nd record data length %u
+# highest F1h~Library End Record
+>>>>>>(1.s+3)	ubyte	x		\b, 2nd record type %#x
+>>>>>>(1.s+4)	uleshort x		\b, 2nd record data length %u
 0	leshort		0xff65		x.out
 >2	string		__.SYMDEF	 randomized
 >0	byte		x		archive
@@ -100,3 +103,4 @@
 >0x1e	leshort		&0x102		Huge Objects Enabled
 
 0	leshort		0x580		XENIX 8086 relocatable or 80286 small model
+# GRR: line above is too general as it catches also all 8086 relocatable (Microsoft) with 1st record data length 5 C0M.OBJ C0T.OBJ C0S.OBJ
--- a/magic/Magdir/xilinx
+++ b/magic/Magdir/xilinx
@@ -1,6 +1,6 @@
 
 #------------------------------------------------------------------------------
-# $File: xilinx,v 1.9 2021/04/26 15:56:00 christos Exp $
+# $File: xilinx,v 1.10 2022/12/18 14:59:32 christos Exp $
 # This is Aaron's attempt at a MAGIC file for Xilinx .bit files.
 # Xilinx-Magic@RevRagnarok.com
 # Got the info from FPGA-FAQ 0026
@@ -38,3 +38,21 @@
 # Raw bitstream files
 0      long    0xffffffff
 >&0    belong  0xaa995566      Xilinx RAW bitstream (.BIN)
+
+# AXLF (xclbin) files used by AMD/Xilinx accelerators.
+# The file format is defined by XRT source tree:
+# https://github.com/Xilinx/XRT/blob/master/src/runtime_src/core/include/xclbin.h
+# Display file size, creation date, accelerator shell name, xclbin uuid and
+# number of sections.
+
+0       string      xclbin2     AMD/Xilinx accelerator AXLF (xclbin) file
+>0x130  lequad      x           \b, %lld bytes
+>0x138  leqdate     x           \b, created %s
+>0x160  string      >0          \b, shell "%.64s"
+>0x1a0  ubelong     x           \b, uuid %08x
+>0x1a4  ubeshort    x           \b-%04x
+>0x1a6  ubeshort    x           \b-%04x
+>0x1a8  ubeshort    x           \b-%04x
+>0x1aa  ubelong     x           \b-%08x
+>0x1ae  ubeshort    x           \b%04x
+>0x1c0  lelong      x           \b, %d sections
\ No newline at end of file
--- a/magic/Makefile.am
+++ b/magic/Makefile.am
@@ -1,5 +1,5 @@
 #
-# $File: Makefile.am,v 1.182 2022/09/11 21:04:30 christos Exp $
+# $File: Makefile.am,v 1.186 2022/11/11 14:52:44 christos Exp $
 #
 MAGIC_FRAGMENT_BASE = Magdir
 MAGIC_DIR = $(top_srcdir)/magic
@@ -92,7 +92,6 @@
 $(MAGIC_FRAGMENT_DIR)/diff \
 $(MAGIC_FRAGMENT_DIR)/digital \
 $(MAGIC_FRAGMENT_DIR)/dolby \
-$(MAGIC_FRAGMENT_DIR)/dsf \
 $(MAGIC_FRAGMENT_DIR)/dump \
 $(MAGIC_FRAGMENT_DIR)/dyadic \
 $(MAGIC_FRAGMENT_DIR)/ebml \
@@ -108,6 +107,7 @@
 $(MAGIC_FRAGMENT_DIR)/fcs \
 $(MAGIC_FRAGMENT_DIR)/filesystems \
 $(MAGIC_FRAGMENT_DIR)/finger \
+$(MAGIC_FRAGMENT_DIR)/firmware \
 $(MAGIC_FRAGMENT_DIR)/flash \
 $(MAGIC_FRAGMENT_DIR)/flif \
 $(MAGIC_FRAGMENT_DIR)/fonts \
@@ -245,6 +245,7 @@
 $(MAGIC_FRAGMENT_DIR)/pgp-binary-keys \
 $(MAGIC_FRAGMENT_DIR)/pkgadd \
 $(MAGIC_FRAGMENT_DIR)/plan9 \
+$(MAGIC_FRAGMENT_DIR)/playdate \
 $(MAGIC_FRAGMENT_DIR)/plus5 \
 $(MAGIC_FRAGMENT_DIR)/pmem \
 $(MAGIC_FRAGMENT_DIR)/polyml \
@@ -267,6 +268,7 @@
 $(MAGIC_FRAGMENT_DIR)/rtf \
 $(MAGIC_FRAGMENT_DIR)/rst \
 $(MAGIC_FRAGMENT_DIR)/ruby \
+$(MAGIC_FRAGMENT_DIR)/rust \
 $(MAGIC_FRAGMENT_DIR)/sc \
 $(MAGIC_FRAGMENT_DIR)/sccs \
 $(MAGIC_FRAGMENT_DIR)/scientific \
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,10 +17,10 @@
 else
 MINGWLIBS =
 endif
-libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS)
+libmagic_la_LIBADD = -lm $(LTLIBOBJS) $(MINGWLIBS)
 
 file_SOURCES = file.c seccomp.c
-file_LDADD = libmagic.la
+file_LDADD = libmagic.la -lm
 CLEANFILES = magic.h
 EXTRA_DIST = magic.h.in cdf.mk BNF memtest.c
 HDR= $(top_srcdir)/src/magic.h.in
--- a/src/apprentice.c
+++ b/src/apprentice.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: apprentice.c,v 1.326 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: apprentice.c,v 1.338 2022/10/23 13:21:42 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -476,7 +476,6 @@
 {
 	struct magic_map *map;
 #ifndef COMPILE_ONLY
-	struct mlist *ml;
 	size_t i;
 #endif
 
@@ -498,7 +497,7 @@
 	map = apprentice_map(ms, fn);
 	if (map == NULL) {
 		if (ms->flags & MAGIC_CHECK)
-			file_magwarn(ms, "using regular magic file `%s'", fn);
+			file_magwarn(NULL, "using regular magic file `%s'", fn);
 		map = apprentice_load(ms, fn, action);
 		if (map == NULL)
 			return -1;
@@ -511,7 +510,7 @@
 				apprentice_unmap(map);
 			else
 				mlist_free_all(ms);
-			file_oomem(ms, sizeof(*ml));
+			file_oomem(ms, sizeof(*ms->mlist[0]));
 			return -1;
 		}
 	}
@@ -555,7 +554,7 @@
 	size_t i, len;
 
 	if ((ms = CAST(struct magic_set *, calloc(CAST(size_t, 1u),
-	    sizeof(struct magic_set)))) == NULL)
+	    sizeof(*ms)))) == NULL)
 		return NULL;
 
 	if (magic_setflags(ms, flags) == -1) {
@@ -693,7 +692,6 @@
     size_t *sizes, size_t nbufs)
 {
 	size_t i, j;
-	struct mlist *ml;
 	struct magic_map *map;
 
 	if (nbufs == 0)
@@ -706,7 +704,7 @@
 	for (i = 0; i < MAGIC_SETS; i++) {
 		mlist_free(ms->mlist[i]);
 		if ((ms->mlist[i] = mlist_alloc()) == NULL) {
-			file_oomem(ms, sizeof(*ms->mlist[i]));
+			file_oomem(ms, sizeof(*ms->mlist[0]));
 			goto fail;
 		}
 	}
@@ -718,7 +716,7 @@
 
 		for (j = 0; j < MAGIC_SETS; j++) {
 			if (add_mlist(ms->mlist[j], map, j) == -1) {
-				file_oomem(ms, sizeof(*ml));
+				file_oomem(ms, sizeof(*ms->mlist[0]));
 				goto fail;
 			}
 		}
@@ -754,7 +752,7 @@
 	for (i = 0; i < MAGIC_SETS; i++) {
 		mlist_free(ms->mlist[i]);
 		if ((ms->mlist[i] = mlist_alloc()) == NULL) {
-			file_oomem(ms, sizeof(*ms->mlist[i]));
+			file_oomem(ms, sizeof(*ms->mlist[0]));
 			for (j = 0; j < i; j++) {
 				mlist_free(ms->mlist[j]);
 				ms->mlist[j] = NULL;
@@ -942,8 +940,8 @@
 	switch (m->type) {
 	case FILE_DEFAULT:	/* make sure this sorts last */
 		if (m->factor_op != FILE_FACTOR_OP_NONE) {
-			fprintf(stderr, "Bad factor_op %d", m->factor_op);
-			abort();
+			file_magwarn(NULL, "Usupported factor_op in default %d",
+			    m->factor_op);
 		}
 		return 0;
 
@@ -1169,14 +1167,16 @@
 			 * description/mimetype.
 			 */
 			lineindex = descindex = mimeindex = magindex;
-			for (magindex++; magindex < ml->nmagic &&
-			   ml->magic[magindex].cont_level != 0; magindex++) {
+			for (; magindex + 1 < ml->nmagic &&
+			   ml->magic[magindex + 1].cont_level != 0;
+			   magindex++) {
+				uint32_t mi = magindex + 1;
 				if (*ml->magic[descindex].desc == '\0'
-				    && *ml->magic[magindex].desc)
-					descindex = magindex;
+				    && *ml->magic[mi].desc)
+					descindex = mi;
 				if (*ml->magic[mimeindex].mimetype == '\0'
-				    && *ml->magic[magindex].mimetype)
-					mimeindex = magindex;
+				    && *ml->magic[mi].mimetype)
+					mimeindex = mi;
 			}
 
 			printf("Strength = %3" SIZE_T_FORMAT "u@%u: %s [%s]\n",
@@ -1591,7 +1591,7 @@
 			i = set_text_binary(ms, mset[j].me, mset[j].count, i);
 		}
 		if (mset[j].me)
-			qsort(mset[j].me, mset[j].count, sizeof(*mset[j].me),
+			qsort(mset[j].me, mset[j].count, sizeof(*mset[0].me),
 			    apprentice_sort);
 
 		/*
@@ -2436,6 +2436,7 @@
 	const char *l = line;
 	char *el;
 	unsigned long factor;
+	char sbuf[512];
 	struct magic *m = &me->mp[0];
 
 	if (m->factor_op != FILE_FACTOR_OP_NONE) {
@@ -2446,12 +2447,15 @@
 	}
 	if (m->type == FILE_NAME) {
 		file_magwarn(ms, "%s: Strength setting is not supported in "
-		    "\"name\" magic entries", m->value.s);
+		    "\"name\" magic entries",
+		    file_printable(ms, sbuf, sizeof(sbuf), m->value.s,
+		    sizeof(m->value.s)));
 		return -1;
 	}
 	EATAB;
 	switch (*l) {
 	case FILE_FACTOR_OP_NONE:
+		break;
 	case FILE_FACTOR_OP_PLUS:
 	case FILE_FACTOR_OP_MINUS:
 	case FILE_FACTOR_OP_TIMES:
@@ -2762,6 +2766,7 @@
 	}
 invalid:
 	*estr = "not valid";
+	return -1;
 toolong:
 	*estr = "too long";
 	return -1;
@@ -2832,6 +2837,7 @@
 {
 	char *ep;
 	uint64_t ull;
+	int y;
 
 	switch (m->type) {
 	case FILE_BESTRING16:
@@ -2853,8 +2859,8 @@
 		}
 		if (m->type == FILE_REGEX) {
 			file_regex_t rx;
-			int rc = file_regcomp(ms, &rx, m->value.s,
-			    REG_EXTENDED);
+			int rc =
+			    file_regcomp(ms, &rx, m->value.s, REG_EXTENDED);
 			if (rc == 0) {
 				file_regfree(&rx);
 			}
@@ -2899,6 +2905,7 @@
 		m->value.q = file_signextend(ms, m, ull);
 		if (*p == ep) {
 			file_magwarn(ms, "Unparsable number `%s'", *p);
+			return -1;
 		} else {
 			size_t ts = typesize(m->type);
 			uint64_t x;
@@ -2908,32 +2915,38 @@
 				file_magwarn(ms,
 				    "Expected numeric type got `%s'",
 				    type_tbl[m->type].name);
+				return -1;
 			}
 			for (q = *p; isspace(CAST(unsigned char, *q)); q++)
 				continue;
-			if (*q == '-')
+			if (*q == '-' && ull != UINT64_MAX)
 				ull = -CAST(int64_t, ull);
 			switch (ts) {
 			case 1:
 				x = CAST(uint64_t, ull & ~0xffULL);
+				y = (x & ~0xffULL) != ~0xffULL;
 				break;
 			case 2:
 				x = CAST(uint64_t, ull & ~0xffffULL);
+				y = (x & ~0xffffULL) != ~0xffffULL;
 				break;
 			case 4:
 				x = CAST(uint64_t, ull & ~0xffffffffULL);
+				y = (x & ~0xffffffffULL) != ~0xffffffffULL;
 				break;
 			case 8:
 				x = 0;
+				y = 0;
 				break;
 			default:
 				fprintf(stderr, "Bad width %zu", ts);
 				abort();
 			}
-			if (x) {
+			if (x && y) {
 				file_magwarn(ms, "Overflow for numeric"
 				    " type `%s' value %#" PRIx64,
 				    type_tbl[m->type].name, ull);
+				return -1;
 			}
 		}
 		if (errno == 0) {
--- a/src/apptype.c
+++ b/src/apptype.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: apptype.c,v 1.14 2018/09/09 20:33:28 christos Exp $")
+FILE_RCSID("@(#)$File: apptype.c,v 1.16 2022/09/24 20:30:13 christos Exp $")
 #endif /* lint */
 
 #include <stdlib.h>
--- a/src/ascmagic.c
+++ b/src/ascmagic.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: ascmagic.c,v 1.110 2021/12/06 15:33:00 christos Exp $")
+FILE_RCSID("@(#)$File: ascmagic.c,v 1.112 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
--- a/src/asctime_r.c
+++ b/src/asctime_r.c
@@ -1,8 +1,8 @@
-/*	$File: asctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $	*/
+/*	$File: asctime_r.c,v 1.3 2022/09/24 20:30:13 christos Exp $	*/
 
 #include "file.h"
 #ifndef	lint
-FILE_RCSID("@(#)$File: asctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $")
+FILE_RCSID("@(#)$File: asctime_r.c,v 1.3 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 #include <time.h>
 #include <string.h>
--- a/src/asprintf.c
+++ b/src/asprintf.c
@@ -29,7 +29,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: asprintf.c,v 1.5 2018/09/09 20:33:28 christos Exp $")
+FILE_RCSID("@(#)$File: asprintf.c,v 1.7 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 int asprintf(char **ptr, const char *fmt, ...)
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: buffer.c,v 1.8 2020/02/16 15:52:49 christos Exp $")
+FILE_RCSID("@(#)$File: buffer.c,v 1.10 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
--- a/src/cdf.c
+++ b/src/cdf.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf.c,v 1.121 2021/10/20 13:56:15 christos Exp $")
+FILE_RCSID("@(#)$File: cdf.c,v 1.123 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <assert.h>
--- a/src/cdf_time.c
+++ b/src/cdf_time.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: cdf_time.c,v 1.20 2021/12/06 15:33:00 christos Exp $")
+FILE_RCSID("@(#)$File: cdf_time.c,v 1.23 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <time.h>
@@ -157,7 +157,7 @@
 		return -1;
 	}
 	*t = (ts->ts_nsec / 100) * CDF_TIME_PREC;
-	*t = tm.tm_sec;
+	*t += tm.tm_sec;
 	*t += tm.tm_min * 60;
 	*t += tm.tm_hour * 60 * 60;
 	*t += tm.tm_mday * 60 * 60 * 24;
--- a/src/compress.c
+++ b/src/compress.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: compress.c,v 1.136 2022/09/13 16:08:34 christos Exp $")
+FILE_RCSID("@(#)$File: compress.c,v 1.152 2022/10/31 13:22:26 christos Exp $")
 #endif
 
 #include "magic.h"
@@ -79,6 +79,17 @@
 #include <lzma.h>
 #endif
 
+#if defined(HAVE_ZSTD_H) && defined(ZSTDLIBSUPPORT)
+#define BUILTIN_ZSTDLIB
+#include <zstd.h>
+#include <zstd_errors.h>
+#endif
+
+#if defined(HAVE_LZLIB_H) && defined(LZLIBSUPPORT)
+#define BUILTIN_LZLIB
+#include <lzlib.h>
+#endif
+
 #ifdef DEBUG
 int tty = -1;
 #define DPRINTF(...)	do { \
@@ -175,6 +186,8 @@
 #define METH_FROZEN	2
 #define METH_BZIP	7
 #define METH_XZ		9
+#define METH_LZIP	8
+#define METH_ZSTD	12
 #define METH_LZMA	13
 #define METH_ZLIB	14
     { { .magic = "\037\235" },	2, gzip_args, NULL },	/* 0, compressed */
@@ -207,21 +220,29 @@
 private ssize_t swrite(int, const void *, size_t);
 #if HAVE_FORK
 private size_t ncompr = __arraycount(compr);
-private int uncompressbuf(int, size_t, size_t, const unsigned char *,
+private int uncompressbuf(int, size_t, size_t, int, const unsigned char *,
     unsigned char **, size_t *);
 #ifdef BUILTIN_DECOMPRESS
 private int uncompresszlib(const unsigned char *, unsigned char **, size_t,
     size_t *, int);
 private int uncompressgzipped(const unsigned char *, unsigned char **, size_t,
-    size_t *);
+    size_t *, int);
 #endif
 #ifdef BUILTIN_BZLIB
 private int uncompressbzlib(const unsigned char *, unsigned char **, size_t,
-    size_t *);
+    size_t *, int);
 #endif
 #ifdef BUILTIN_XZLIB
 private int uncompressxzlib(const unsigned char *, unsigned char **, size_t,
-    size_t *);
+    size_t *, int);
+#endif
+#ifdef BUILTIN_ZSTDLIB
+private int uncompresszstd(const unsigned char *, unsigned char **, size_t,
+    size_t *, int);
+#endif
+#ifdef BUILTIN_LZLIB
+private int uncompresslzlib(const unsigned char *, unsigned char **, size_t,
+    size_t *, int);
 #endif
 
 static int makeerror(unsigned char **, size_t *, const char *, ...)
@@ -287,7 +308,9 @@
 		}
 
 		nsz = nbytes;
-		urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz);
+		free(newbuf);
+		urv = uncompressbuf(fd, ms->bytes_max, i, 
+		    (ms->flags & MAGIC_NO_COMPRESS_FORK), buf, &newbuf, &nsz);
 		DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv,
 		    (char *)newbuf, nsz);
 		switch (urv) {
@@ -297,7 +320,8 @@
 			if (urv == ERRDATA)
 				prv = format_decompression_error(ms, i, newbuf);
 			else
-				prv = file_buffer(ms, -1, NULL, name, newbuf, nsz);
+				prv = file_buffer(ms, -1, NULL, name, newbuf,
+				    nsz);
 			if (prv == -1)
 				goto error;
 			rv = 1;
@@ -314,7 +338,8 @@
 			 * XXX: If file_buffer fails here, we overwrite
 			 * the compressed text. FIXME.
 			 */
-			if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1) {
+			if (file_buffer(ms, -1, NULL, NULL, buf, nbytes) == -1)
+			{
 				if (file_pop_buffer(ms, pb) != NULL)
 					abort();
 				goto error;
@@ -538,11 +563,17 @@
 
 private int
 uncompressgzipped(const unsigned char *old, unsigned char **newch,
-    size_t bytes_max, size_t *n)
+    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
 {
-	unsigned char flg = old[3];
+	unsigned char flg;
 	size_t data_start = 10;
 
+	if (*n < 4) {
+		goto err;	
+	}
+
+	flg = old[3];
+
 	if (flg & FEXTRA) {
 		if (data_start + 1 >= *n)
 			goto err;
@@ -578,9 +609,6 @@
 	int rc;
 	z_stream z;
 
-	if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL)
-		return makeerror(newch, n, "No buffer, %s", strerror(errno));
-
 	z.next_in = CCAST(Bytef *, old);
 	z.avail_in = CAST(uint32_t, *n);
 	z.next_out = *newch;
@@ -595,8 +623,10 @@
 		goto err;
 
 	rc = inflate(&z, Z_SYNC_FLUSH);
-	if (rc != Z_OK && rc != Z_STREAM_END)
+	if (rc != Z_OK && rc != Z_STREAM_END) {
+		inflateEnd(&z);
 		goto err;
+	}
 
 	*n = CAST(size_t, z.total_out);
 	rc = inflateEnd(&z);
@@ -608,16 +638,14 @@
 
 	return OKDATA;
 err:
-	strlcpy(RCAST(char *, *newch), z.msg ? z.msg : zError(rc), bytes_max);
-	*n = strlen(RCAST(char *, *newch));
-	return ERRDATA;
+	return makeerror(newch, n, "%s", z.msg ? z.msg : zError(rc));
 }
 #endif
 
 #ifdef BUILTIN_BZLIB
 private int
 uncompressbzlib(const unsigned char *old, unsigned char **newch,
-    size_t bytes_max, size_t *n)
+    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
 {
 	int rc;
 	bz_stream bz;
@@ -627,17 +655,16 @@
 	if (rc != BZ_OK)
 		goto err;
 
-	if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL)
-		return makeerror(newch, n, "No buffer, %s", strerror(errno));
-
 	bz.next_in = CCAST(char *, RCAST(const char *, old));
 	bz.avail_in = CAST(uint32_t, *n);
 	bz.next_out = RCAST(char *, *newch);
 	bz.avail_out = CAST(unsigned int, bytes_max);
 
 	rc = BZ2_bzDecompress(&bz);
-	if (rc != BZ_OK && rc != BZ_STREAM_END)
+	if (rc != BZ_OK && rc != BZ_STREAM_END) {
+		BZ2_bzDecompressEnd(&bz);
 		goto err;
+	}
 
 	/* Assume byte_max is within 32bit */
 	/* assert(bz.total_out_hi32 == 0); */
@@ -651,16 +678,14 @@
 
 	return OKDATA;
 err:
-	snprintf(RCAST(char *, *newch), bytes_max, "bunzip error %d", rc);
-	*n = strlen(RCAST(char *, *newch));
-	return ERRDATA;
+	return makeerror(newch, n, "bunzip error %d", rc);
 }
 #endif
 
 #ifdef BUILTIN_XZLIB
 private int
 uncompressxzlib(const unsigned char *old, unsigned char **newch,
-    size_t bytes_max, size_t *n)
+    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
 {
 	int rc;
 	lzma_stream xz;
@@ -670,17 +695,16 @@
 	if (rc != LZMA_OK)
 		goto err;
 
-	if ((*newch = CAST(unsigned char *, malloc(bytes_max + 1))) == NULL)
-		return makeerror(newch, n, "No buffer, %s", strerror(errno));
-
 	xz.next_in = CCAST(const uint8_t *, old);
 	xz.avail_in = CAST(uint32_t, *n);
 	xz.next_out = RCAST(uint8_t *, *newch);
 	xz.avail_out = CAST(unsigned int, bytes_max);
 
 	rc = lzma_code(&xz, LZMA_RUN);
-	if (rc != LZMA_OK && rc != LZMA_STREAM_END)
+	if (rc != LZMA_OK && rc != LZMA_STREAM_END) {
+		lzma_end(&xz);
 		goto err;
+	}
 
 	*n = CAST(size_t, xz.total_out);
 
@@ -691,9 +715,113 @@
 
 	return OKDATA;
 err:
-	snprintf(RCAST(char *, *newch), bytes_max, "unxz error %d", rc);
-	*n = strlen(RCAST(char *, *newch));
-	return ERRDATA;
+	return makeerror(newch, n, "unxz error %d", rc);
+}
+#endif
+
+#ifdef BUILTIN_ZSTDLIB
+private int
+uncompresszstd(const unsigned char *old, unsigned char **newch,
+    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
+{
+	size_t rc;
+	ZSTD_DStream *zstd;
+	ZSTD_inBuffer in;
+	ZSTD_outBuffer out;
+
+	if ((zstd = ZSTD_createDStream()) == NULL) {
+		return makeerror(newch, n, "No ZSTD decompression stream, %s",
+		    strerror(errno));
+	}
+
+	rc = ZSTD_DCtx_reset(zstd, ZSTD_reset_session_only);
+	if (ZSTD_isError(rc))
+		goto err;
+
+	in.src = CCAST(const void *, old);
+	in.size = *n;
+	in.pos = 0;
+	out.dst = RCAST(void *, *newch);
+	out.size = bytes_max;
+	out.pos = 0;
+
+	rc = ZSTD_decompressStream(zstd, &out, &in);
+	if (ZSTD_isError(rc))
+		goto err;
+
+	*n = out.pos;
+
+	ZSTD_freeDStream(zstd);
+
+	/* let's keep the nul-terminate tradition */
+	(*newch)[*n] = '\0';
+
+	return OKDATA;
+err:
+	ZSTD_freeDStream(zstd);
+	return makeerror(newch, n, "zstd error %d", ZSTD_getErrorCode(rc));
+}
+#endif
+
+#ifdef BUILTIN_LZLIB
+private int
+uncompresslzlib(const unsigned char *old, unsigned char **newch,
+    size_t bytes_max, size_t *n, int extra __attribute__((__unused__)))
+{
+	enum LZ_Errno err;
+	size_t old_remaining = *n;
+	size_t new_remaining = bytes_max;
+	size_t total_read = 0;
+	unsigned char *bufp;
+	struct LZ_Decoder *dec;
+
+	bufp = *newch;
+
+	dec = LZ_decompress_open();
+	if (!dec) {
+		return makeerror(newch, n, "unable to allocate LZ_Decoder");
+	}
+	if (LZ_decompress_errno(dec) != LZ_ok)
+		goto err;
+
+	for (;;) {
+		// LZ_decompress_read() stops at member boundaries, so we may
+		// have more than one successful read after writing all data
+		// we have.
+		if (old_remaining > 0) {
+			int wr = LZ_decompress_write(dec, old, old_remaining);
+			if (wr < 0)
+				goto err;
+			old_remaining -= wr;
+			old += wr;
+		}
+
+		int rd = LZ_decompress_read(dec, bufp, new_remaining);
+		if (rd > 0) {
+			new_remaining -= rd;
+			bufp += rd;
+			total_read += rd;
+		}
+
+		if (rd < 0 || LZ_decompress_errno(dec) != LZ_ok)
+			goto err;
+		if (new_remaining == 0)
+			break;
+		if (old_remaining == 0 && rd == 0)
+			break;
+	}
+
+	LZ_decompress_close(dec);
+	*n = total_read;
+
+	/* let's keep the nul-terminate tradition */
+	*bufp = '\0';
+
+	return OKDATA;
+err:
+	err = LZ_decompress_errno(dec);
+	LZ_decompress_close(dec);
+	return makeerror(newch, n, "lzlib error: %s", LZ_strerror(err));
 }
 #endif
 
@@ -705,6 +833,7 @@
 	va_list ap;
 	int rv;
 
+	free(*buf);
 	va_start(ap, fmt);
 	rv = vasprintf(&msg, fmt, ap);
 	va_end(ap);
@@ -747,7 +876,7 @@
 #else
 	if (dup2(fd, i) == -1) {
 		DPRINTF("dup(%d, %d) failed (%s)\n", fd, i, strerror(errno));
-		exit(1);
+		exit(EXIT_FAILURE);
 	}
 	close(v ? fd : fd);
 #endif
@@ -804,15 +933,15 @@
 	pid = fork();
 	if (pid == -1) {
 		DPRINTF("Fork failed (%s)\n", strerror(errno));
-		exit(1);
+		return -1;
 	}
 	if (pid == 0) {
 		/* child */
 		if (swrite(fd, old, n) != CAST(ssize_t, n)) {
 			DPRINTF("Write failed (%s)\n", strerror(errno));
-			exit(1);
+			exit(EXIT_FAILURE);
 		}
-		exit(0);
+		exit(EXIT_SUCCESS);
 	}
 	/* parent */
 	return pid;
@@ -864,44 +993,79 @@
 	case METH_LZMA:
 		return "xzlib";
 #endif
+#ifdef BUILTIN_ZSTDLIB
+	case METH_ZSTD:
+		return "zstd";
+#endif
+#ifdef BUILTIN_LZLIB
+	case METH_LZIP:
+		return "lzlib";
+#endif
 	default:
 		return compr[method].argv[0];
 	}
 }
 
-private int
-uncompressbuf(int fd, size_t bytes_max, size_t method, const unsigned char *old,
-    unsigned char **newch, size_t* n)
+private int (*
+getdecompressor(int method))(const unsigned char *, unsigned char **, size_t,
+    size_t *, int)
 {
-	int fdp[3][2];
-	int status, rv, w;
-	pid_t pid;
-	pid_t writepid = -1;
-	size_t i;
-	ssize_t r;
-	char *const *args;
-#ifdef HAVE_POSIX_SPAWNP
-	posix_spawn_file_actions_t fa;
-#endif
-
 	switch (method) {
 #ifdef BUILTIN_DECOMPRESS
 	case METH_FROZEN:
-		return uncompressgzipped(old, newch, bytes_max, n);
+		return uncompressgzipped;
 	case METH_ZLIB:
-		return uncompresszlib(old, newch, bytes_max, n, 1);
+		return uncompresszlib;
 #endif
 #ifdef BUILTIN_BZLIB
 	case METH_BZIP:
-		return uncompressbzlib(old, newch, bytes_max, n);
+		return uncompressbzlib;
 #endif
 #ifdef BUILTIN_XZLIB
 	case METH_XZ:
 	case METH_LZMA:
-		return uncompressxzlib(old, newch, bytes_max, n);
+		return uncompressxzlib;
+#endif
+#ifdef BUILTIN_ZSTDLIB
+	case METH_ZSTD:
+		return uncompresszstd;
+#endif
+#ifdef BUILTIN_LZLIB
+	case METH_LZIP:
+		return uncompresslzlib;
 #endif
 	default:
-		break;
+		return NULL;
+	}
+}
+
+private int
+uncompressbuf(int fd, size_t bytes_max, size_t method, int nofork,
+    const unsigned char *old, unsigned char **newch, size_t* n)
+{
+	int fdp[3][2];
+	int status, rv, w;
+	pid_t pid;
+	pid_t writepid = -1;
+	size_t i;
+	ssize_t r;
+	char *const *args;
+#ifdef HAVE_POSIX_SPAWNP
+	posix_spawn_file_actions_t fa;
+#endif
+	int (*decompress)(const unsigned char *, unsigned char **,
+	    size_t, size_t *, int) = getdecompressor(method);
+
+	*newch = CAST(unsigned char *, malloc(bytes_max + 1));
+	if (*newch == NULL)
+		return makeerror(newch, n, "No buffer, %s", strerror(errno));
+
+	if (decompress) {
+		if (nofork) {
+			return makeerror(newch, n,
+			    "Fork is required to uncompress, but disabled");
+		}
+		return (*decompress)(old, newch, bytes_max, n, 1);
 	}
 
 	(void)fflush(stdout);
@@ -916,7 +1080,7 @@
 	 * analyze two large compressed files, both will spawn
 	 * an uncompressing child here, which writes out uncompressed data.
 	 * We read some portion, then close the pipe, then waitpid() the child.
-	 * If uncompressed data is larger, child shound get EPIPE and exit.
+	 * If uncompressed data is larger, child should get EPIPE and exit.
 	 * However, with *parallel* calls OTHER child may unintentionally
 	 * inherit pipe fds, thus keeping pipe open and making writes in
 	 * our child block instead of failing with EPIPE!
@@ -968,7 +1132,7 @@
 		(void)execvp(compr[method].argv[0], args);
 		dprintf(STDERR_FILENO, "exec `%s' failed, %s",
 		    compr[method].argv[0], strerror(errno));
-		_exit(1); /* _exit(), not exit(), because of vfork */
+		_exit(EXIT_FAILURE); /* _exit(), not exit(), because of vfork */
 	}
 #endif
 	/* parent */
@@ -979,39 +1143,41 @@
 	if (fd == -1) {
 		closefd(fdp[STDIN_FILENO], 0);
 		writepid = writechild(fdp[STDIN_FILENO][1], old, *n);
+		if (writepid == (pid_t)-1) {
+			rv = makeerror(newch, n, "Write to child failed, %s",
+			    strerror(errno));
+			goto err;
+		}
 		closefd(fdp[STDIN_FILENO], 1);
 	}
 
-	*newch = CAST(unsigned char *, malloc(bytes_max + 1));
-	if (*newch == NULL) {
-		rv = makeerror(newch, n, "No buffer, %s",
-		    strerror(errno));
-		goto err;
-	}
 	rv = OKDATA;
-	errno = 0;
 	r = sread(fdp[STDOUT_FILENO][0], *newch, bytes_max, 0);
-	if (r == 0 && errno == 0)
-		goto ok;
-	if (r <= 0) {
-		DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
-		    r != -1 ? strerror(errno) : "no data");
-
+	if (r < 0) {
 		rv = ERRDATA;
-		if (r == 0 &&
-		    (r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0)
-		{
-			r = filter_error(*newch, r);
-			goto ok;
-		}
-		free(*newch);
-		if  (r == 0)
-			rv = makeerror(newch, n, "Read failed, %s",
-			    strerror(errno));
-		else
-			rv = makeerror(newch, n, "No data");
+		DPRINTF("Read stdout failed %d (%s)\n", fdp[STDOUT_FILENO][0],
+		        strerror(errno));
 		goto err;
+	} 
+	if (CAST(size_t, r) == bytes_max) {
+		/*
+		 * close fd so that the child exits with sigpipe and ignore
+		 * errors, otherwise we risk the child blocking and never
+		 * exiting.
+		 */
+		closefd(fdp[STDOUT_FILENO], 0);
+		goto ok;
 	}
+	if ((r = sread(fdp[STDERR_FILENO][0], *newch, bytes_max, 0)) > 0) {
+		rv = ERRDATA;
+		r = filter_error(*newch, r);
+		goto ok;
+	}
+	if  (r == 0)
+		goto ok;
+	rv = makeerror(newch, n, "Read stderr failed, %s",
+	    strerror(errno));
+	goto err;
 ok:
 	*n = r;
 	/* NUL terminate, as every buffer is handled here. */
@@ -1024,7 +1190,6 @@
 	w = waitpid(pid, &status, 0);
 wait_err:
 	if (w == -1) {
-		free(*newch);
 		rv = makeerror(newch, n, "Wait failed, %s", strerror(errno));
 		DPRINTF("Child wait return %#x\n", status);
 	} else if (!WIFEXITED(status)) {
--- a/src/ctime_r.c
+++ b/src/ctime_r.c
@@ -1,8 +1,8 @@
-/*	$File: ctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $	*/
+/*	$File: ctime_r.c,v 1.3 2022/09/24 20:30:13 christos Exp $	*/
 
 #include "file.h"
 #ifndef	lint
-FILE_RCSID("@(#)$File: ctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $")
+FILE_RCSID("@(#)$File: ctime_r.c,v 1.3 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 #include <time.h>
 #include <string.h>
--- a/src/der.c
+++ b/src/der.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: der.c,v 1.24 2022/07/30 18:08:36 christos Exp $")
+FILE_RCSID("@(#)$File: der.c,v 1.27 2022/09/24 20:30:13 christos Exp $")
 #endif
 #else
 #define SIZE_T_FORMAT "z"
@@ -270,7 +270,7 @@
 		DPRINTF(("%s: bad tag 1\n", __func__));
 		return -1;
 	}
-	DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
+	DPRINTF(("%s1: %u %" SIZE_T_FORMAT "u %d\n", __func__, ms->offset,
 	    offs, m->offset));
 
 	uint32_t tlen = getlength(b, &offs, len);
@@ -278,7 +278,7 @@
 		DPRINTF(("%s: bad tag 2\n", __func__));
 		return -1;
 	}
-	DPRINTF(("%s2: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
+	DPRINTF(("%s2: %u %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
 	    offs, tlen));
 
 	offs += ms->offset + m->offset;
@@ -286,14 +286,14 @@
 #ifdef DEBUG_DER
 	size_t i;
 	for (i = 0; i < m->cont_level; i++)
-		printf("cont_level[%" SIZE_T_FORMAT "u] = %u\n", i,
+		printf("cont_level[%" SIZE_T_FORMAT "u] = %d\n", i,
 		    ms->c.li[i].off);
 #endif
 	if (m->cont_level != 0) {
 		if (offs + tlen > nbytes)
 			return -1;
 		ms->c.li[m->cont_level - 1].off = CAST(int, offs + tlen);
-		DPRINTF(("cont_level[%u] = %u\n", m->cont_level - 1,
+		DPRINTF(("cont_level[%u] = %d\n", m->cont_level - 1,
 		    ms->c.li[m->cont_level - 1].off));
 	}
 	return CAST(int32_t, offs);
@@ -316,7 +316,7 @@
 		return -1;
 	}
 
-	DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %u\n", __func__, ms->offset,
+	DPRINTF(("%s1: %d %" SIZE_T_FORMAT "u %d\n", __func__, ms->offset,
 	    offs, m->offset));
 
 	tlen = getlength(b, &offs, len);
--- a/src/dprintf.c
+++ b/src/dprintf.c
@@ -28,7 +28,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: dprintf.c,v 1.2 2018/09/09 20:33:28 christos Exp $")
+FILE_RCSID("@(#)$File: dprintf.c,v 1.4 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include <assert.h>
--- a/src/encoding.c
+++ b/src/encoding.c
@@ -35,7 +35,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: encoding.c,v 1.39 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: encoding.c,v 1.41 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
--- a/src/file.c
+++ b/src/file.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: file.c,v 1.204 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: file.c,v 1.212 2022/10/26 18:09:26 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -366,6 +366,8 @@
 	if (sandbox && enable_sandbox_full() == -1)
 #endif
 		file_err(EXIT_FAILURE, "SECCOMP initialisation failed");
+	if (sandbox)
+		flags |= MAGIC_NO_COMPRESS_FORK;
 #endif /* HAVE_LIBSECCOMP */
 
 	if (MAGIC_VERSION != magic_version())
@@ -512,11 +514,8 @@
 	size_t llen = 0;
 	int wid = 0, cwid;
 	int e = 0;
-	size_t fi = 0, fimax = 100;
-	char **flist = CAST(char **, malloc(sizeof(*flist) * fimax));
-
-	if (flist == NULL)
-out:		file_err(EXIT_FAILURE, "Cannot allocate memory for file list");
+	size_t fi = 0, fimax = 0;
+	char **flist = NULL;
 
 	if (strcmp("-", fn) == 0)
 		f = stdin;
@@ -530,26 +529,37 @@
 	while ((len = getline(&line, &llen, f)) > 0) {
 		if (line[len - 1] == '\n')
 			line[len - 1] = '\0';
+		cwid = file_mbswidth(ms, line);
+		if (nobuffer) {
+			e |= process(ms, line, cwid);
+			free(line);
+			line = NULL;
+			llen = 0;
+			continue;
+		}
+		if (cwid > wid)
+			wid = cwid;
 		if (fi >= fimax) {
 			fimax += 100;
 			char **nf = CAST(char **,
 			    realloc(flist, fimax * sizeof(*flist)));
-			if (nf == NULL)
-				goto out;
+			if (nf == NULL) {
+				file_err(EXIT_FAILURE,
+				    "Cannot allocate memory for file list");
+			}
 			flist = nf;
 		}
 		flist[fi++] = line;
-		cwid = file_mbswidth(ms, line);
-		if (cwid > wid)
-			wid = cwid;
 		line = NULL;
 		llen = 0;
 	}
 
-	fimax = fi;
-	for (fi = 0; fi < fimax; fi++) {
-		e |= process(ms, flist[fi], wid);
-		free(flist[fi]);
+	if (!nobuffer) {
+		fimax = fi;
+		for (fi = 0; fi < fimax; fi++) {
+			e |= process(ms, flist[fi], wid);
+			free(flist[fi]);
+		}
 	}
 	free(flist);
 
@@ -561,10 +571,10 @@
 private void
 file_octal(unsigned char c)
 {
-	putc('\\', stdout);
-	putc(((c >> 6) & 7) + '0', stdout);
-	putc(((c >> 3) & 7) + '0', stdout);
-	putc(((c >> 0) & 7) + '0', stdout);
+	(void)putc('\\', stdout);
+	(void)putc(((c >> 6) & 7) + '0', stdout);
+	(void)putc(((c >> 3) & 7) + '0', stdout);
+	(void)putc(((c >> 0) & 7) + '0', stdout);
 }
 
 private void
@@ -591,7 +601,7 @@
 		inname += bytesconsumed;
 		n -= bytesconsumed;
 		if (iswprint(nextchar)) {
-			printf("%lc", nextchar);
+			printf("%lc", (wint_t)nextchar);
 			continue;
 		}
 		/* XXX: What if it is > 255? */
@@ -602,7 +612,7 @@
 	for (i = 0; i < n; i++) {
 		unsigned char c = CAST(unsigned char, inname[i]);
 		if (isprint(c)) {
-			putc(c);
+			(void)putc(c, stdout);
 			continue;
 		}
 		file_octal(c);
@@ -698,8 +708,8 @@
 	if (!def)
 		return;
 	if (((def & 1) && posixly) || ((def & 2) && !posixly))
-		fprintf(stdout, " (default)");
-	fputc('\n', stdout);
+		(void)fprintf(stdout, " (default)");
+	(void)putc('\n', stdout);
 }
 
 private void
@@ -711,7 +721,7 @@
 
 	p = CCAST(char *, strchr(opts, '%'));
 	if (p == NULL) {
-		fprintf(stdout, "%s", opts);
+		(void)fprintf(stdout, "%s", opts);
 		defprint(def);
 		return;
 	}
@@ -719,26 +729,26 @@
 	for (sp = p - 1; sp > opts && *sp == ' '; sp--)
 		continue;
 
-	fprintf(stdout, "%.*s", CAST(int, p - opts), opts);
+	(void)printf("%.*s", CAST(int, p - opts), opts);
 	pad = (int)CAST(int, p - sp - 1);
 
 	switch (*++p) {
 	case 'e':
 		comma = 0;
 		for (i = 0; i < __arraycount(nv); i++) {
-			fprintf(stdout, "%s%s", comma++ ? ", " : "", nv[i].name);
+			(void)printf("%s%s", comma++ ? ", " : "", nv[i].name);
 			if (i && i % 5 == 0 && i != __arraycount(nv) - 1) {
-				fprintf(stdout, ",\n%*s", pad, "");
+				(void)printf(",\n%*s", pad, "");
 				comma = 0;
 			}
 		}
 		break;
 	case 'P':
 		for (i = 0; i < __arraycount(pm); i++) {
-			fprintf(stdout, "%9s %7zu %s", pm[i].name, pm[i].def,
+			(void)printf("%9s %7zu %s", pm[i].name, pm[i].def,
 			    pm[i].desc);
 			if (i != __arraycount(pm) - 1)
-				fprintf(stdout, "\n%*s", pad, "");
+				(void)printf("\n%*s", pad, "");
 		}
 		break;
 	default:
@@ -746,7 +756,7 @@
 		   *p);
 		break;
 	}
-	fprintf(stdout, "%s", opts + (p - opts) + 1);
+	(void)printf("%s", opts + (p - opts) + 1);
 
 }
 
@@ -758,15 +768,15 @@
 "Determine type of FILEs.\n"
 "\n", stdout);
 #define OPT(shortname, longname, opt, def, doc)      \
-	fprintf(stdout, "  -%c, --" longname, shortname), \
+	(void)printf("  -%c, --" longname, shortname), \
 	docprint(doc, def);
 #define OPT_LONGONLY(longname, opt, def, doc, id)    	\
-	fprintf(stdout, "      --" longname),	\
+	(void)printf("      --" longname),	\
 	docprint(doc, def);
 #include "file_opts.h"
 #undef OPT
 #undef OPT_LONGONLY
-	fprintf(stdout, "\nReport bugs to https://bugs.astron.com/\n");
+	(void)printf("\nReport bugs to https://bugs.astron.com/\n");
 	exit(EXIT_SUCCESS);
 }
 
@@ -791,11 +801,11 @@
 	int se = errno;
 
 	va_start(ap, fmt);
-	fprintf(stderr, "%s: ", file_progname);
-	vfprintf(stderr, fmt, ap);
+	(void)fprintf(stderr, "%s: ", file_progname);
+	(void)vfprintf(stderr, fmt, ap);
 	va_end(ap);
 	if (se)
-		fprintf(stderr, " (%s)\n", strerror(se));
+		(void)fprintf(stderr, " (%s)\n", strerror(se));
 	else
 		fputc('\n', stderr);
 	exit(e);
@@ -807,10 +817,10 @@
 	va_list ap;
 
 	va_start(ap, fmt);
-	fprintf(stderr, "%s: ", file_progname);
-	vfprintf(stderr, fmt, ap);
+	(void)fprintf(stderr, "%s: ", file_progname);
+	(void)vfprintf(stderr, fmt, ap);
 	va_end(ap);
-	fprintf(stderr, "\n");
+	(void)fprintf(stderr, "\n");
 	exit(e);
 }
 
@@ -821,11 +831,11 @@
 	int se = errno;
 
 	va_start(ap, fmt);
-	fprintf(stderr, "%s: ", file_progname);
-	vfprintf(stderr, fmt, ap);
+	(void)fprintf(stderr, "%s: ", file_progname);
+	(void)vfprintf(stderr, fmt, ap);
 	va_end(ap);
 	if (se)
-		fprintf(stderr, " (%s)\n", strerror(se));
+		(void)fprintf(stderr, " (%s)\n", strerror(se));
 	else
 		fputc('\n', stderr);
 	errno = se;
@@ -838,9 +848,9 @@
 	int se = errno;
 
 	va_start(ap, fmt);
-	fprintf(stderr, "%s: ", file_progname);
-	vfprintf(stderr, fmt, ap);
+	(void)fprintf(stderr, "%s: ", file_progname);
+	(void)vfprintf(stderr, fmt, ap);
 	va_end(ap);
-	fprintf(stderr, "\n");
+	(void)fprintf(stderr, "\n");
 	errno = se;
 }
--- a/src/file.h
+++ b/src/file.h
@@ -27,7 +27,7 @@
  */
 /*
  * file.h - definitions for file(1) program
- * @(#)$File: file.h,v 1.237 2022/09/10 13:21:42 christos Exp $
+ * @(#)$File: file.h,v 1.240 2022/10/02 12:53:28 christos Exp $
  */
 
 #ifndef __file_h__
@@ -483,8 +483,8 @@
 	size_t bytes_max;		/* number of bytes to read from file */
 	size_t encoding_max;		/* bytes to look for encoding */
 #ifndef FILE_BYTES_MAX
-# define FILE_BYTES_MAX (1024 * 1024)	/* how much of the file to look at */
-#endif
+# define FILE_BYTES_MAX (7 * 1024 * 1024)/* how much of the file to look at */
+#endif /* above 0x6ab0f4 map offset for HelveticaNeue.dfont */
 #define	FILE_ELF_NOTES_MAX		256
 #define	FILE_ELF_PHNUM_MAX		2048
 #define	FILE_ELF_SHNUM_MAX		32768
--- a/src/file_opts.h
+++ b/src/file_opts.h
@@ -37,7 +37,7 @@
     "                               performed for file. Valid tests are:\n"
     "                               %e\n")
 OPT_LONGONLY("exclude-quiet", 1, 0,
-    " TEST         like exclude, but ignore unknown tests\n", OPT_EXCLUDE_QUIET)
+    " TEST   like exclude, but ignore unknown tests\n", OPT_EXCLUDE_QUIET)
 OPT('f', "files-from", 1, 0,
     " FILE      read the filenames to be examined from FILE\n")
 OPT('F', "separator", 1, 0,
@@ -59,9 +59,9 @@
     "                 list magic strength\n")
 #ifdef S_IFLNK
 OPT('L', "dereference", 0, 1,
-    "          follow symlinks")
+    "          follow symlinks (default if POSIXLY_CORRECT is set)")
 OPT('h', "no-dereference", 0, 2,
-    "       don't follow symlinks")
+    "       don't follow symlinks (default if POSIXLY_CORRECT is not set)")
 #endif
 OPT('n', "no-buffer", 0, 0,
     "            do not buffer output\n")
--- a/src/fmtcheck.c
+++ b/src/fmtcheck.c
@@ -30,7 +30,7 @@
 
 #include "file.h"
 #ifndef lint
-FILE_RCSID("@(#)$File: fmtcheck.c,v 1.4 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: fmtcheck.c,v 1.6 2022/09/24 20:30:13 christos Exp $")
 #endif /* lint */
 
 #include <stdio.h>
--- a/src/fsmagic.c
+++ b/src/fsmagic.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: fsmagic.c,v 1.82 2022/04/11 18:14:41 christos Exp $")
+FILE_RCSID("@(#)$File: fsmagic.c,v 1.84 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
--- a/src/funcs.c
+++ b/src/funcs.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: funcs.c,v 1.131 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: funcs.c,v 1.135 2022/10/09 13:44:47 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
@@ -656,10 +656,43 @@
 	return rv;
 }
 
+private int
+check_regex(struct magic_set *ms, const char *pat)
+{
+	char sbuf[512];
+	unsigned char oc = '\0';
+
+	for (const char *p = pat; *p; p++) {
+		unsigned char c = *p;
+		// Avoid repetition
+		if (c == oc && strchr("?*+{", c) != NULL) {
+			size_t len = strlen(pat);
+			file_magwarn(ms,
+			    "repetition-operator operand `%c' "
+			    "invalid in regex `%s'", c,
+			    file_printable(ms, sbuf, sizeof(sbuf), pat, len));
+			return -1;
+		}
+		oc = c;
+		if (isprint(c) || isspace(c) || c == '\b'
+		    || c == 0x8a) // XXX: apple magic fixme
+			continue;
+		size_t len = strlen(pat);
+		file_magwarn(ms,
+		    "non-ascii characters in regex \\%#o `%s'",
+		    c, file_printable(ms, sbuf, sizeof(sbuf), pat, len));
+		return -1;
+	}
+	return 0;
+}
+
 protected int
 file_regcomp(struct magic_set *ms file_locale_used, file_regex_t *rx,
     const char *pat, int flags)
 {
+	if (check_regex(ms, pat) == -1)
+		return -1;
+
 #ifdef USE_C_LOCALE
 	locale_t old = uselocale(ms->c_lc_ctype);
 	assert(old != NULL);
@@ -677,10 +710,11 @@
 	(void)setlocale(LC_CTYPE, old);
 #endif
 	if (rc > 0 && (ms->flags & MAGIC_CHECK)) {
-		char errmsg[512];
+		char errmsg[512], buf[512];
 
 		(void)regerror(rc, rx, errmsg, sizeof(errmsg));
-		file_magerror(ms, "regex error %d for `%s', (%s)", rc, pat,
+		file_magerror(ms, "regex error %d for `%s', (%s)", rc, 
+		    file_printable(ms, buf, sizeof(buf), pat, strlen(pat)),
 		    errmsg);
 	}
 	return rc;
--- a/src/getopt_long.c
+++ b/src/getopt_long.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: getopt_long.c,v 1.7 2018/09/09 20:33:28 christos Exp $")
+FILE_RCSID("@(#)$File: getopt_long.c,v 1.9 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include <assert.h>
--- a/src/gmtime_r.c
+++ b/src/gmtime_r.c
@@ -1,8 +1,8 @@
-/*	$File: gmtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $	*/
+/*	$File: gmtime_r.c,v 1.4 2022/09/24 20:30:13 christos Exp $	*/
 
 #include "file.h"
 #ifndef	lint
-FILE_RCSID("@(#)$File: gmtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $")
+FILE_RCSID("@(#)$File: gmtime_r.c,v 1.4 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 #include <time.h>
 #include <string.h>
--- a/src/is_csv.c
+++ b/src/is_csv.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: is_csv.c,v 1.7 2022/05/28 00:44:22 christos Exp $")
+FILE_RCSID("@(#)$File: is_csv.c,v 1.10 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <string.h>
@@ -174,7 +174,7 @@
 int
 main(int argc, char *argv[])
 {
-	int fd, rv;
+	int fd;
 	struct stat st;
 	unsigned char *p;
 
--- a/src/is_json.c
+++ b/src/is_json.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: is_json.c,v 1.26 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: is_json.c,v 1.30 2022/09/27 19:12:40 christos Exp $")
 #endif
 
 #include "magic.h"
@@ -440,7 +440,7 @@
 		return 1;
 	if (mime) {
 		if (file_printf(ms, "application/%s",
-		    jt == 1 ? "json" : "x-ndjason") == -1)
+		    jt == 1 ? "json" : "x-ndjson") == -1)
 			return -1;
 		return 1;
 	}
@@ -475,7 +475,7 @@
 int
 main(int argc, char *argv[])
 {
-	int fd, rv;
+	int fd;
 	struct stat st;
 	unsigned char *p;
 	size_t stats[JSON_MAX];
--- a/src/is_tar.c
+++ b/src/is_tar.c
@@ -40,7 +40,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: is_tar.c,v 1.47 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: is_tar.c,v 1.49 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include "magic.h"
--- a/src/localtime_r.c
+++ b/src/localtime_r.c
@@ -1,8 +1,8 @@
-/*	$File: localtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $	*/
+/*	$File: localtime_r.c,v 1.4 2022/09/24 20:30:13 christos Exp $	*/
 
 #include "file.h"
 #ifndef	lint
-FILE_RCSID("@(#)$File: localtime_r.c,v 1.2 2015/07/11 14:41:37 christos Exp $")
+FILE_RCSID("@(#)$File: localtime_r.c,v 1.4 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 #include <time.h>
 #include <string.h>
--- a/src/magic.c
+++ b/src/magic.c
@@ -33,7 +33,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: magic.c,v 1.117 2021/12/06 15:33:00 christos Exp $")
+FILE_RCSID("@(#)$File: magic.c,v 1.119 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
--- a/src/magic.h.in
+++ b/src/magic.h.in
@@ -47,6 +47,8 @@
 					   * extensions */
 #define MAGIC_COMPRESS_TRANSP	0x2000000 /* Check inside compressed files
 					   * but not report compression */
+#define MAGIC_NO_COMPRESS_FORK	0x4000000 /* Don't allow decompression that
+					   * needs to fork */
 #define MAGIC_NODESC		(MAGIC_EXTENSION|MAGIC_MIME|MAGIC_APPLE)
 
 #define	MAGIC_NO_CHECK_COMPRESS	0x0001000 /* Don't check for compressed files */
--- a/src/memtest.c
+++ b/src/memtest.c
@@ -24,9 +24,10 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+#include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: memtest.c,v 1.3 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: memtest.c,v 1.6 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <sys/types.h>
--- a/src/pread.c
+++ b/src/pread.c
@@ -1,6 +1,6 @@
 #include "file.h"
 #ifndef lint
-FILE_RCSID("@(#)$File: pread.c,v 1.3 2014/09/15 19:11:25 christos Exp $")
+FILE_RCSID("@(#)$File: pread.c,v 1.5 2022/09/24 20:30:13 christos Exp $")
 #endif  /* lint */
 #include <fcntl.h>
 #include <unistd.h>
--- a/src/print.c
+++ b/src/print.c
@@ -32,7 +32,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: print.c,v 1.92 2022/09/10 13:21:42 christos Exp $")
+FILE_RCSID("@(#)$File: print.c,v 1.96 2022/09/27 01:58:20 christos Exp $")
 #endif  /* lint */
 
 #include <string.h>
@@ -52,7 +52,7 @@
 	static const char optyp[] = { FILE_OPS };
 	char tbuf[256];
 
-	(void) fprintf(stderr, "%u: %.*s %u", m->lineno,
+	(void) fprintf(stderr, "%u: %.*s %d", m->lineno,
 	    (m->cont_level & 7) + 1, ">>>>>>>>", m->offset);
 
 	if (m->flag & INDIR) {
@@ -62,7 +62,7 @@
 		    "*bad in_type*");
 		if (m->in_op & FILE_OPINVERSE)
 			(void) fputc('~', stderr);
-		(void) fprintf(stderr, "%c%u),",
+		(void) fprintf(stderr, "%c%d),",
 		    (CAST(size_t, m->in_op & FILE_OPS_MASK) <
 		    __arraycount(optyp)) ?
 		    optyp[m->in_op & FILE_OPS_MASK] : '?', m->in_offset);
@@ -134,7 +134,7 @@
 		case FILE_BESHORT:
 		case FILE_BELONG:
 		case FILE_INDIRECT:
-			(void) fprintf(stderr, "%d", m->value.l);
+			(void) fprintf(stderr, "%d", CAST(int32_t, m->value.l));
 			break;
 		case FILE_BEQUAD:
 		case FILE_LEQUAD:
@@ -250,7 +250,7 @@
 	/* cuz we use stdout for most, stderr here */
 	(void) fflush(stdout);
 
-	if (ms->file)
+	if (ms && ms->file)
 		(void) fprintf(stderr, "%s, %lu: ", ms->file,
 		    CAST(unsigned long, ms->line));
 	(void) fprintf(stderr, "Warning: ");
@@ -263,7 +263,8 @@
 protected const char *
 file_fmtvarint(char *buf, size_t blen, const unsigned char *us, int t)
 {
-	snprintf(buf, blen, "%jd", file_varint2uintmax_t(us, t, NULL));
+	snprintf(buf, blen, "%jd", CAST(intmax_t,
+	    file_varint2uintmax_t(us, t, NULL)));
 	return buf;
 }
 
--- a/src/readcdf.c
+++ b/src/readcdf.c
@@ -26,7 +26,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readcdf.c,v 1.76 2022/01/17 16:59:01 christos Exp $")
+FILE_RCSID("@(#)$File: readcdf.c,v 1.78 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <assert.h>
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef lint
-FILE_RCSID("@(#)$File: readelf.c,v 1.182 2022/07/31 16:01:01 christos Exp $")
+FILE_RCSID("@(#)$File: readelf.c,v 1.186 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #ifdef BUILTIN_ELF
@@ -451,6 +451,10 @@
 
 		if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
 			return -1;
+		if (ver_maj >= 9) {
+			ver_patch += 100 * ver_rel;
+			ver_rel = 0;
+		}
 		if (ver_rel == 0 && ver_patch != 0) {
 			if (file_printf(ms, ".%u", ver_patch) == -1)
 				return -1;
@@ -460,8 +464,7 @@
 					return -1;
 				ver_rel -= 26;
 			}
-			if (file_printf(ms, "%c", 'A' + ver_rel - 1)
-			    == -1)
+			if (file_printf(ms, "%c", 'A' + ver_rel - 1) == -1)
 				return -1;
 		}
 	}
--- a/src/seccomp.c
+++ b/src/seccomp.c
@@ -27,7 +27,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: seccomp.c,v 1.22 2022/07/30 16:49:18 christos Exp $")
+FILE_RCSID("@(#)$File: seccomp.c,v 1.24 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #if HAVE_LIBSECCOMP
--- a/src/softmagic.c
+++ b/src/softmagic.c
@@ -32,11 +32,12 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: softmagic.c,v 1.328 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: softmagic.c,v 1.337 2022/12/14 14:24:36 christos Exp $")
 #endif	/* lint */
 
 #include "magic.h"
 #include <assert.h>
+#include <math.h>
 #include <string.h>
 #include <ctype.h>
 #include <stdlib.h>
@@ -45,11 +46,11 @@
 
 private int match(struct magic_set *, struct magic *, file_regex_t **, size_t,
     const struct buffer *, size_t, int, int, int, uint16_t *,
-    uint16_t *, int *, int *, int *, int *);
+    uint16_t *, int *, int *, int *, int *, int *);
 private int mget(struct magic_set *, struct magic *, const struct buffer *,
     const unsigned char *, size_t,
     size_t, unsigned int, int, int, int, uint16_t *,
-    uint16_t *, int *, int *, int *, int *);
+    uint16_t *, int *, int *, int *, int *, int *);
 private int msetoffset(struct magic_set *, struct magic *, struct buffer *,
     const struct buffer *, size_t, unsigned int);
 private int magiccheck(struct magic_set *, struct magic *, file_regex_t **);
@@ -118,7 +119,7 @@
     uint16_t *indir_count, uint16_t *name_count, int mode, int text)
 {
 	struct mlist *ml;
-	int rv = 0, printed_something = 0, need_separator = 0;
+	int rv = 0, printed_something = 0, need_separator = 0, firstline = 1;
 	uint16_t nc, ic;
 
 	if (name_count == NULL) {
@@ -133,7 +134,8 @@
 	for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) {
 		int ret = match(ms, ml->magic, ml->magic_rxcomp, ml->nmagic, b,
 		    0, mode, text, 0, indir_count, name_count,
-		    &printed_something, &need_separator, NULL, NULL);
+		    &printed_something, &need_separator, &firstline,
+		    NULL, NULL);
 		switch (ret) {
 		case -1:
 			return ret;
@@ -205,15 +207,13 @@
 match(struct magic_set *ms, struct magic *magic, file_regex_t **magic_rxcomp,
     size_t nmagic, const struct buffer *b, size_t offset, int mode, int text,
     int flip, uint16_t *indir_count, uint16_t *name_count,
-    int *printed_something, int *need_separator, int *returnval,
-    int *found_match)
+    int *printed_something, int *need_separator, int *firstline,
+    int *returnval, int *found_match)
 {
 	uint32_t magindex = 0;
 	unsigned int cont_level = 0;
 	int found_matchv = 0; /* if a match is found it is set to 1*/
 	int returnvalv = 0, e;
-	/* a flag to print X\n  X\n- X */
-	int firstline = !(*printed_something || *need_separator);
 	struct buffer bb;
 	int print = (ms->flags & MAGIC_NODESC) == 0;
 
@@ -257,7 +257,8 @@
 		switch (mget(ms, m, b, CAST(const unsigned char *, bb.fbuf),
 		    bb.flen, offset, cont_level,
 		    mode, text, flip, indir_count, name_count,
-		    printed_something, need_separator, returnval, found_match))
+		    printed_something, need_separator, firstline, returnval,
+		    found_match))
 		{
 		case -1:
 			return -1;
@@ -290,7 +291,7 @@
 			goto flush;
 		}
 
-		if ((e = handle_annotation(ms, m, firstline)) != 0)
+		if ((e = handle_annotation(ms, m, *firstline)) != 0)
 		{
 			*found_match = 1;
 			*need_separator = 1;
@@ -309,7 +310,7 @@
 				*returnval = 1;
 				*need_separator = 1;
 				*printed_something = 1;
-				if (print_sep(ms, firstline) == -1)
+				if (print_sep(ms, *firstline) == -1)
 					return -1;
 				if (mprint(ms, m) == -1)
 					return -1;
@@ -368,7 +369,7 @@
 			    bb.fbuf), bb.flen, offset,
 			    cont_level, mode, text, flip, indir_count,
 			    name_count, printed_something, need_separator,
-			    returnval, found_match)) {
+			    firstline, returnval, found_match)) {
 			case -1:
 				return -1;
 			case 0:
@@ -405,7 +406,7 @@
 				} else
 					ms->c.li[cont_level].got_match = 1;
 
-				if ((e = handle_annotation(ms, m, firstline))
+				if ((e = handle_annotation(ms, m, *firstline))
 				    != 0) {
 					*found_match = 1;
 					*need_separator = 1;
@@ -431,7 +432,7 @@
 					 */
 					if (!*printed_something) {
 						*printed_something = 1;
-						if (print_sep(ms, firstline)
+						if (print_sep(ms, *firstline)
 						    == -1)
 							return -1;
 					}
@@ -467,14 +468,14 @@
 			}
 		}
 		if (*printed_something) {
-			firstline = 0;
+			*firstline = 0;
 		}
 		if (*found_match) {
 			if ((ms->flags & MAGIC_CONTINUE) == 0)
 				return *returnval;
 			// So that we print a separator
 			*printed_something = 0;
-			firstline = 0;
+			*firstline = 0;
 		}
 		cont_level = 0;
 	}
@@ -1320,6 +1321,7 @@
 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
     const unsigned char *s, uint32_t offset, size_t nbytes, struct magic *m)
 {
+	size_t size = sizeof(*p);
 	/*
 	 * Note: FILE_SEARCH and FILE_REGEX do not actually copy
 	 * anything, but setup pointers into the source
@@ -1417,6 +1419,9 @@
 		}
 		case FILE_STRING:	/* XXX - these two should not need */
 		case FILE_PSTRING:	/* to copy anything, but do anyway. */
+			if (m->str_range != 0 && m->str_range < sizeof(*p))
+				size = m->str_range;
+			break;
 		default:
 			break;
 		}
@@ -1432,10 +1437,10 @@
 		(void)memset(p, '\0', sizeof(*p));
 		return 0;
 	}
-	if (nbytes - offset < sizeof(*p))
+	if (nbytes - offset < size)
 		nbytes = nbytes - offset;
 	else
-		nbytes = sizeof(*p);
+		nbytes = size;
 
 	(void)memcpy(p, s + offset, nbytes);
 
@@ -1449,10 +1454,17 @@
 	return 0;
 }
 
-private uint32_t
-do_ops(struct magic *m, intmax_t lhs, intmax_t off)
+private int
+do_ops(struct magic *m, uint32_t *rv, intmax_t lhs, intmax_t off)
 {
 	intmax_t offset;
+	// On purpose not INTMAX_MAX
+	if (lhs >= INT_MAX || lhs <= INT_MIN ||
+	    off >= INT_MAX || off <= INT_MIN) {
+		fprintf(stderr, "lhs/off overflow %jd %jd\n", lhs, off);
+		return 1;
+	}
+	   
 	if (off) {
 		switch (m->in_op & FILE_OPS_MASK) {
 		case FILE_OPAND:
@@ -1484,8 +1496,12 @@
 		offset = lhs;
 	if (m->in_op & FILE_OPINVERSE)
 		offset = ~offset;
-
-	return CAST(uint32_t, offset);
+	if (offset >= UINT_MAX) {
+		fprintf(stderr, "offset overflow %jd\n", offset);
+		return 1;
+	}
+	*rv = CAST(uint32_t, offset);
+	return 0;
 }
 
 private int
@@ -1564,7 +1580,7 @@
 mget(struct magic_set *ms, struct magic *m, const struct buffer *b,
     const unsigned char *s, size_t nbytes, size_t o, unsigned int cont_level,
     int mode, int text, int flip, uint16_t *indir_count, uint16_t *name_count,
-    int *printed_something, int *need_separator, int *returnval,
+    int *printed_something, int *need_separator, int *firstline, int *returnval,
     int *found_match)
 {
 	uint32_t eoffset, offset = ms->offset;
@@ -1685,22 +1701,26 @@
 		case FILE_BYTE:
 			if (OFFSET_OOB(nbytes, offset, 1))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,8,p->b), off);
+			if (do_ops(m, &offset, SEXT(sgn,8,p->b), off))
+				return 0;
 			break;
 		case FILE_BESHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,16,BE16(p)), off);
+			if (do_ops(m, &offset, SEXT(sgn,16,BE16(p)), off))
+				return 0;
 			break;
 		case FILE_LESHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,16,LE16(p)), off);
+			if (do_ops(m, &offset, SEXT(sgn,16,LE16(p)), off))
+				return 0;
 			break;
 		case FILE_SHORT:
 			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,16,p->h), off);
+			if (do_ops(m, &offset, SEXT(sgn,16,p->h), off))
+				return 0;
 			break;
 		case FILE_BELONG:
 		case FILE_BEID3:
@@ -1709,7 +1729,8 @@
 			lhs = BE32(p);
 			if (in_type == FILE_BEID3)
 				lhs = cvt_id3(ms, CAST(uint32_t, lhs));
-			offset = do_ops(m, SEXT(sgn,32,lhs), off);
+			if (do_ops(m, &offset, SEXT(sgn,32,lhs), off))
+				return 0;
 			break;
 		case FILE_LELONG:
 		case FILE_LEID3:
@@ -1718,33 +1739,39 @@
 			lhs = LE32(p);
 			if (in_type == FILE_LEID3)
 				lhs = cvt_id3(ms, CAST(uint32_t, lhs));
-			offset = do_ops(m, SEXT(sgn,32,lhs), off);
+			if (do_ops(m, &offset, SEXT(sgn,32,lhs), off))
+				return 0;
 			break;
 		case FILE_MELONG:
 			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,32,ME32(p)), off);
+			if (do_ops(m, &offset, SEXT(sgn,32,ME32(p)), off))
+				return 0;
 			break;
 		case FILE_LONG:
 			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,32,p->l), off);
+			if (do_ops(m, &offset, SEXT(sgn,32,p->l), off))
+				return 0;
 			break;
 		case FILE_LEQUAD:
 			if (OFFSET_OOB(nbytes, offset, 8))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,64,LE64(p)), off);
+			if (do_ops(m, &offset, SEXT(sgn,64,LE64(p)), off))	
+				return 0;
 			break;
 		case FILE_BEQUAD:
 			if (OFFSET_OOB(nbytes, offset, 8))
 				return 0;
-			offset = do_ops(m, SEXT(sgn,64,BE64(p)), off);
+			if (do_ops(m, &offset, SEXT(sgn,64,BE64(p)), off))
+				return 0;
 			break;
 		case FILE_OCTAL:
 			if (OFFSET_OOB(nbytes, offset, m->vallen))
 				return 0;
-			offset = do_ops(m,
-			    SEXT(sgn,64,strtoull(p->s, NULL, 8)), off);
+			if(do_ops(m, &offset,
+			    SEXT(sgn,64,strtoull(p->s, NULL, 8)), off))
+				return 0;
 			break;
 		default:
 			if ((ms->flags & MAGIC_DEBUG) != 0)
@@ -1863,7 +1890,7 @@
 			if ((rv = match(ms, mlp->magic, mlp->magic_rxcomp,
 			    mlp->nmagic, &bb, 0, BINTEST, text, 0, indir_count,
 			    name_count, printed_something, need_separator,
-			    NULL, NULL)) != 0)
+			    firstline, NULL, NULL)) != 0)
 				break;
 		}
 
@@ -1915,7 +1942,7 @@
 		eoffset = ms->eoffset;
 		rv = match(ms, ml.magic, ml.magic_rxcomp, ml.nmagic, b,
 		    offset + o, mode, text, flip, indir_count, name_count,
-		    printed_something, need_separator, returnval,
+		    printed_something, need_separator, firstline, returnval,
 		    &nfound_match);
 		ms->ms_value.q = nfound_match;
 		(*name_count)--;
@@ -1927,7 +1954,7 @@
 		    *need_separator = oneed_separator;
 		ms->offset = offset;
 		ms->eoffset = eoffset;
-		return rv;
+		return rv || *found_match;
 
 	case FILE_NAME:
 		if (ms->flags & MAGIC_NODESC)
@@ -2126,19 +2153,19 @@
 			break;
 
 		case '!':
-			matched = fv != fl;
+			matched = isunordered(fl, fv) ? 1 : fv != fl;
 			break;
 
 		case '=':
-			matched = fv == fl;
+			matched = isunordered(fl, fv) ? 0 : fv == fl;
 			break;
 
 		case '>':
-			matched = fv > fl;
+			matched = isgreater(fv, fl);
 			break;
 
 		case '<':
-			matched = fv < fl;
+			matched = isless(fv, fl);
 			break;
 
 		default:
@@ -2159,19 +2186,19 @@
 			break;
 
 		case '!':
-			matched = dv != dl;
+			matched = isunordered(dv, dl) ? 1 : dv != dl;
 			break;
 
 		case '=':
-			matched = dv == dl;
+			matched = isunordered(dv, dl) ? 0 : dv == dl;
 			break;
 
 		case '>':
-			matched = dv > dl;
+			matched = isgreater(dv, dl);
 			break;
 
 		case '<':
-			matched = dv < dl;
+			matched = isless(dv, dl);
 			break;
 
 		default:
@@ -2212,6 +2239,12 @@
 		slen = MIN(m->vallen, sizeof(m->value.s));
 		l = 0;
 		v = 0;
+		if ((ms->flags & MAGIC_DEBUG) != 0) {
+			fprintf(stderr, "search: [");
+			file_showstr(stderr, ms->search.s, ms->search.s_len);
+			fprintf(stderr, "] for [");
+			file_showstr(stderr, m->value.s, slen);
+		}
 #ifdef HAVE_MEMMEM
 		if (slen > 0 && m->str_flags == 0) {
 			const char *found;
@@ -2220,6 +2253,10 @@
 				idx = ms->search.s_len;
 			found = CAST(const char *, memmem(ms->search.s, idx,
 			    m->value.s, slen));
+			if ((ms->flags & MAGIC_DEBUG) != 0) {
+				fprintf(stderr, "] %sfound\n",
+				    found ? "" : "not ");
+			}
 			if (!found) {
 				v = 1;
 				break;
@@ -2245,6 +2282,9 @@
 				break;
 			}
 		}
+		if ((ms->flags & MAGIC_DEBUG) != 0) {
+			fprintf(stderr, "] %sfound\n", v == 0 ? "" : "not ");
+		}
 		break;
 	}
 	case FILE_REGEX: {
--- a/src/strlcat.c
+++ b/src/strlcat.c
@@ -19,7 +19,7 @@
 /* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
 #include "file.h"
 #ifndef lint
-FILE_RCSID("@(#)$File: strlcat.c,v 1.3 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: strlcat.c,v 1.5 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <sys/types.h>
--- a/src/strlcpy.c
+++ b/src/strlcpy.c
@@ -19,7 +19,7 @@
 /* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */
 #include "file.h"
 #ifndef lint
-FILE_RCSID("@(#)$File: strlcpy.c,v 1.3 2022/09/13 18:46:07 christos Exp $")
+FILE_RCSID("@(#)$File: strlcpy.c,v 1.5 2022/09/24 20:30:13 christos Exp $")
 #endif
 
 #include <sys/types.h>
--- a/src/tar.h
+++ b/src/tar.h
@@ -32,7 +32,7 @@
  *
  * Created 25 August 1985 by John Gilmore, ihnp4!hoptoad!gnu.
  *
- * $File: tar.h,v 1.13 2010/11/30 14:58:53 rrt Exp $ # checkin only
+ * $File: tar.h,v 1.15 2022/09/24 20:30:13 christos Exp $ # checkin only
  */
 
 /*
--- a/src/vasprintf.c
+++ b/src/vasprintf.c
@@ -108,7 +108,7 @@
 #include "file.h"
 
 #ifndef	lint
-FILE_RCSID("@(#)$File: vasprintf.c,v 1.20 2022/07/30 17:04:18 christos Exp $")
+FILE_RCSID("@(#)$File: vasprintf.c,v 1.23 2022/09/24 20:30:13 christos Exp $")
 #endif	/* lint */
 
 #include <assert.h>
@@ -139,8 +139,6 @@
   size_t       pseudo_len;        /* total length of output text if it were not limited in size */
   size_t       maxlen;
   va_list      vargs;             /* pointer to current position into vargs */
-  char *       sprintf_string;
-  FILE *       fprintf_file;
 } xprintf_struct;
 
 /*
@@ -595,8 +593,6 @@
   }
 
   /* for (v)asnprintf */
-  dummy_base = s->buffer_base;
-
   dummy_base = s->buffer_base + s->real_len;
   save_len = s->real_len;
 
@@ -625,6 +621,7 @@
   xprintf_struct s;
   int retval;
 
+  memset(&s, 0, sizeof(s));
   s.src_string = format_string;
 #ifdef va_copy
   va_copy (s.vargs, vargs);
--- a/tests/CVE-2014-1943.result
+++ b/tests/CVE-2014-1943.result
@@ -1 +1 @@
-Apple Driver Map, blocksize 0
\ No newline at end of file
+Apple Driver Map, blocksize 0
--- a/tests/JW07022A.mp3.result
+++ b/tests/JW07022A.mp3.result
@@ -1 +1 @@
-Audio file with ID3 version 2.2.0, contains: MPEG ADTS, layer III, v1, 96 kbps, 44.1 kHz, Monaural
\ No newline at end of file
+Audio file with ID3 version 2.2.0, contains: MPEG ADTS, layer III, v1, 96 kbps, 44.1 kHz, Monaural
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -17,6 +17,14 @@
 bcachefs.testfile \
 cl8m8ocofedso.result \
 cl8m8ocofedso.testfile \
+cmd1.testfile \
+cmd1.result \
+cmd2.testfile \
+cmd2.result \
+cmd3.testfile \
+cmd3.result \
+cmd4.testfile \
+cmd4.result \
 dsd64-dff.result \
 dsd64-dff.testfile \
 dsd64-dsf.result \
@@ -37,6 +45,8 @@
 issue311docx.testfile \
 issue359xlsx.result \
 issue359xlsx.testfile \
+jpeg-text.result \
+jpeg-text.testfile \
 json1.result \
 json1.testfile \
 json2.result \
@@ -57,6 +67,11 @@
 jsonlines1.result \
 matilde.arm.result \
 matilde.arm.testfile \
+multiple-A.magic \
+multiple-B.magic \
+multiple.flags \
+multiple.result \
+multiple.testfile \
 pcjr.result \
 pcjr.testfile \
 pgp-binary-key-v2-phil.result \
@@ -75,6 +90,12 @@
 pgp-binary-key-v4-rsa-no-userid-secret.testfile \
 pgp-binary-key-v4-rsa-secret-key.result \
 pgp-binary-key-v4-rsa-secret-key.testfile \
+pnm1.result \
+pnm1.testfile \
+pnm2.result \
+pnm2.testfile \
+pnm3.result \
+pnm3.testfile \
 regex-eol.magic \
 regex-eol.result \
 regex-eol.testfile \
@@ -127,14 +148,27 @@
 
 T = $(top_srcdir)/tests
 check-local:
-	MAGIC=$(top_builddir)/magic/magic ./test
 	set -e; \
 	for i in $T/*.testfile; do \
-		echo Running test: $$i; \
-		if [ -f $${i%%.testfile}.magic ]; then \
-			m=$${i%%.testfile}.magic; \
-		else \
+		t=$${i%%.testfile}; \
+		echo Running test: $$t; \
+		m=; \
+		for j in $$(eval echo $${t}\*.magic); do \
+			if [ -f "$$j" ]; then \
+				if [ -z "$$m" ]; then \
+					m=$$j; \
+				else \
+					m=$$m:$$j; \
+				fi \
+			fi \
+		done; \
+		if [ -z "$$m" ]; then \
 			m=$(top_builddir)/magic/magic; \
 		fi; \
-		TZ=UTC MAGIC=$$m ./test $$i $${i%%.testfile}.result; \
+		f=-e; \
+		if [ -f $${t}.flags ]; then \
+			f=$$f$$(cat $${t}.flags); \
+		fi; \
+		echo TZ=UTC MAGIC=$$m ./test $$f $$i $${t}.result; \
+		TZ=UTC MAGIC=$$m ./test $$f $$i $${t}.result; \
 	done
--- a/tests/android-vdex-1.result
+++ b/tests/android-vdex-1.result
@@ -1 +1 @@
-Android vdex file, verifier deps version: 021, dex section version: 002, number of dex files: 4, verifier deps size: 106328
\ No newline at end of file
+Android vdex file, verifier deps version: 021, dex section version: 002, number of dex files: 4, verifier deps size: 106328
--- a/tests/android-vdex-2.result
+++ b/tests/android-vdex-2.result
@@ -1 +1 @@
-Android vdex file, being processed by dex2oat, verifier deps version: 019, dex section version: 002, number of dex files: 1, verifier deps size: 1016
\ No newline at end of file
+Android vdex file, being processed by dex2oat, verifier deps version: 019, dex section version: 002, number of dex files: 1, verifier deps size: 1016
--- a/tests/arj.result
+++ b/tests/arj.result
@@ -1 +1 @@
-ARJ archive data, v11, slash-switched, created 5 1980+48, original name: example_m0.arj, os: Unix
\ No newline at end of file
+ARJ archive data, v11, slash-switched, created 5 1980+48, original name: example_m0.arj, os: Unix
--- a/tests/bcachefs.result
+++ b/tests/bcachefs.result
@@ -1 +1 @@
-bcachefs, UUID=46bd306f-80ad-4cd0-af4f-147e7d85f393, label "Label", version 13, min version 13, device 0/UUID=72a60ede-4cb6-4374-aa70-cb38a50af5ef, 1 devices
\ No newline at end of file
+bcachefs, UUID=46bd306f-80ad-4cd0-af4f-147e7d85f393, label "Label", version 13, min version 13, device 0/UUID=72a60ede-4cb6-4374-aa70-cb38a50af5ef, 1 devices
--- a/tests/cl8m8ocofedso.result
+++ b/tests/cl8m8ocofedso.result
@@ -1 +1 @@
-Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 192 kbps, 44.1 kHz, JntStereo
\ No newline at end of file
+Audio file with ID3 version 2.4.0, contains: MPEG ADTS, layer III, v1, 192 kbps, 44.1 kHz, JntStereo
--- /dev/null
+++ b/tests/cmd1.result
@@ -0,0 +1 @@
+a /usr/bin/cmd1 script, ASCII text executable
--- /dev/null
+++ b/tests/cmd1.testfile
@@ -0,0 +1 @@
+#! /usr/bin/cmd1
--- /dev/null
+++ b/tests/cmd2.result
@@ -0,0 +1 @@
+a /usr/bin/cmd2 script, ASCII text executable
--- /dev/null
+++ b/tests/cmd2.testfile
@@ -0,0 +1 @@
+#!/usr/bin/cmd2
--- /dev/null
+++ b/tests/cmd3.result
@@ -0,0 +1 @@
+a /usr/bin/cmd3 script executable (binary data)
--- /dev/null
+++ b/tests/cmd3.testfile
@@ -0,0 +1,2 @@
+#!/usr/bin/cmd3
+
--- /dev/null
+++ b/tests/cmd4.result
@@ -0,0 +1 @@
+a /usr/bin/cmd4 script executable (binary data)
--- /dev/null
+++ b/tests/cmd4.testfile
@@ -0,0 +1,2 @@
+#!	/usr/bin/cmd4
+
--- a/tests/dsd64-dff.result
+++ b/tests/dsd64-dff.result
@@ -1 +1 @@
-DSDIFF audio bitstream data, 1 bit, mono, "DSD 64" 2822400 Hz, no compression, ID3 version 2.0.0
\ No newline at end of file
+DSDIFF audio bitstream data, 1 bit, mono, "DSD 64" 2822400 Hz, no compression, ID3 version 2.0.0
--- a/tests/dsd64-dsf.result
+++ b/tests/dsd64-dsf.result
@@ -1 +1 @@
-DSF audio bitstream data, 1 bit, mono, "DSD 64" 2822400 Hz, no compression, ID3 version 2.3.0
\ No newline at end of file
+DSF audio bitstream data, 1 bit, mono, "DSD 64" 2822400 Hz, no compression, ID3 version 2.3.0
--- a/tests/escapevel.result
+++ b/tests/escapevel.result
@@ -1 +1 @@
-Zip data (MIME type "application/vnd.nz.gen.geek_central.ti5x"?)
\ No newline at end of file
+Zip data (MIME type "application/vnd.nz.gen.geek_central.ti5x"?)
--- a/tests/ext4.result
+++ b/tests/ext4.result
@@ -1 +1 @@
-Linux rev 1.0 ext4 filesystem data, UUID=d32bbb08-3a76-4510-a064-3045f887dbdf (extents) (64bit) (large files) (huge files)
\ No newline at end of file
+Linux rev 1.0 ext4 filesystem data, UUID=d32bbb08-3a76-4510-a064-3045f887dbdf (extents) (64bit) (large files) (huge files)
--- a/tests/fit-map-data.result
+++ b/tests/fit-map-data.result
@@ -1 +1 @@
-FIT Map data, unit id 65536, serial 3879446968, Sat May 31 10:00:34 2014, manufacturer 1 (garmin), product 1632, type 4 (Activity)
\ No newline at end of file
+FIT Map data, unit id 65536, serial 3879446968, Sat May 31 10:00:34 2014, manufacturer 1 (garmin), product 1632, type 4 (Activity)
--- a/tests/gedcom.result
+++ b/tests/gedcom.result
@@ -1 +1 @@
-GEDCOM genealogy text version 5.5, ASCII text
\ No newline at end of file
+GEDCOM genealogy text version 5.5, ASCII text
--- a/tests/hddrawcopytool.result
+++ b/tests/hddrawcopytool.result
@@ -1 +1 @@
-HDD Raw Copy Tool 1.10 - HD model: ST500DM0 02-1BD142 serial: 51D20233A7C0
\ No newline at end of file
+HDD Raw Copy Tool 1.10 - HD model: ST500DM0 02-1BD142 serial: 51D20233A7C0
--- a/tests/issue311docx.result
+++ b/tests/issue311docx.result
@@ -1 +1 @@
-Microsoft Word 2007+
\ No newline at end of file
+Microsoft Word 2007+
--- a/tests/issue359xlsx.result
+++ b/tests/issue359xlsx.result
@@ -1 +1 @@
-Microsoft Excel 2007+
\ No newline at end of file
+Microsoft Excel 2007+
--- /dev/null
+++ b/tests/jpeg-text.result
@@ -0,0 +1 @@
+ASCII text, with no line terminators
--- /dev/null
+++ b/tests/jpeg-text.testfile
@@ -0,0 +1 @@
+/*! jP
\ No newline at end of file
--- a/tests/json1.result
+++ b/tests/json1.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/json2.result
+++ b/tests/json2.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/json3.result
+++ b/tests/json3.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/json4.result
+++ b/tests/json4.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/json5.result
+++ b/tests/json5.result
@@ -1 +1 @@
-ASCII text
\ No newline at end of file
+ASCII text
--- a/tests/json6.result
+++ b/tests/json6.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/json7.result
+++ b/tests/json7.result
@@ -1 +1 @@
-ASCII text
\ No newline at end of file
+ASCII text
--- a/tests/json8.result
+++ b/tests/json8.result
@@ -1 +1 @@
-JSON text data
\ No newline at end of file
+JSON text data
--- a/tests/jsonlines1.result
+++ b/tests/jsonlines1.result
@@ -1 +1 @@
-New Line Delimited JSON text data
\ No newline at end of file
+New Line Delimited JSON text data
--- a/tests/matilde.arm.result
+++ b/tests/matilde.arm.result
@@ -1 +1 @@
-Adaptive Multi-Rate Codec (GSM telephony)
\ No newline at end of file
+Adaptive Multi-Rate Codec (GSM telephony)
--- /dev/null
+++ b/tests/multiple-A.magic
@@ -0,0 +1,2 @@
+0 search {\\rt1 RTF1.0
+16 search ViVa2 Viva File 2.0
--- /dev/null
+++ b/tests/multiple-B.magic
@@ -0,0 +1,2 @@
+6 search ABCD ABCD File
+10 search TesT Test File 1.0
--- /dev/null
+++ b/tests/multiple.flags
@@ -0,0 +1 @@
+k
--- /dev/null
+++ b/tests/multiple.result
@@ -0,0 +1 @@
+RTF1.0\012- Viva File 2.0\012- ABCD File\012- Test File 1.0, ASCII text, with no line terminators
--- /dev/null
+++ b/tests/multiple.testfile
@@ -0,0 +1 @@
+{\rt1 ABCDTesT xxViVa2
\ No newline at end of file
--- a/tests/pcjr.result
+++ b/tests/pcjr.result
@@ -1 +1 @@
-PCjr Cartridge image
\ No newline at end of file
+PCjr Cartridge image
--- a/tests/pgp-binary-key-v2-phil.result
+++ b/tests/pgp-binary-key-v2-phil.result
@@ -1 +1 @@
-OpenPGP Public Key Version 2, Created Fri May 21 05:20:00 1993, RSA (Encrypt or Sign, 1024 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Public Key Version 2, Created Fri May 21 05:20:00 1993, RSA (Encrypt or Sign, 1024 bits); User ID; Signature; OpenPGP Certificate
--- a/tests/pgp-binary-key-v3-lutz.result
+++ b/tests/pgp-binary-key-v3-lutz.result
@@ -1 +1 @@
-OpenPGP Public Key Version 3, Created Mon Mar 17 11:14:30 1997, RSA (Encrypt or Sign, 1127 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Public Key Version 3, Created Mon Mar 17 11:14:30 1997, RSA (Encrypt or Sign, 1127 bits); User ID; Signature; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-dsa.result
+++ b/tests/pgp-binary-key-v4-dsa.result
@@ -1 +1 @@
-OpenPGP Public Key Version 4, Created Mon Apr  7 22:23:01 1997, DSA (1024 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Public Key Version 4, Created Mon Apr  7 22:23:01 1997, DSA (1024 bits); User ID; Signature; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-ecc-no-userid-secret.result
+++ b/tests/pgp-binary-key-v4-ecc-no-userid-secret.result
@@ -1 +1 @@
-OpenPGP Secret Key Version 4, Created Wed Aug 26 20:52:13 2020, EdDSA; Signature; Secret Subkey; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Secret Key Version 4, Created Wed Aug 26 20:52:13 2020, EdDSA; Signature; Secret Subkey; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-ecc-secret-key.result
+++ b/tests/pgp-binary-key-v4-ecc-secret-key.result
@@ -1 +1 @@
-OpenPGP Secret Key Version 4, Created Sat Aug 22 14:07:46 2020, EdDSA; User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:07:46 2020, EdDSA; User ID; Signature; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-rsa-key.result
+++ b/tests/pgp-binary-key-v4-rsa-key.result
@@ -1 +1 @@
-OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-rsa-no-userid-secret.result
+++ b/tests/pgp-binary-key-v4-rsa-no-userid-secret.result
@@ -1 +1 @@
-OpenPGP Secret Key Version 4, Created Sat Aug 22 20:13:52 2020, RSA (Encrypt or Sign, 3072 bits); Signature; Secret Subkey; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Secret Key Version 4, Created Sat Aug 22 20:13:52 2020, RSA (Encrypt or Sign, 3072 bits); Signature; Secret Subkey; OpenPGP Certificate
--- a/tests/pgp-binary-key-v4-rsa-secret-key.result
+++ b/tests/pgp-binary-key-v4-rsa-secret-key.result
@@ -1 +1 @@
-OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
\ No newline at end of file
+OpenPGP Secret Key Version 4, Created Sat Aug 22 14:05:57 2020, RSA (Encrypt or Sign, 3072 bits); User ID; Signature; OpenPGP Certificate
--- /dev/null
+++ b/tests/pnm1.result
@@ -0,0 +1 @@
+Netpbm image data, size = 2 x 2, greymap, ASCII text
--- /dev/null
+++ b/tests/pnm1.testfile
@@ -0,0 +1,5 @@
+P2
+2
+2
+255
+0 0 0 0
--- /dev/null
+++ b/tests/pnm2.result
@@ -0,0 +1 @@
+Netpbm image data, size = 2 x 2, rawbits, greymap
--- /dev/null
+++ b/tests/pnm3.result
@@ -0,0 +1 @@
+Netpbm image data, size = 10 x 20, pixmap, ASCII text
--- /dev/null
+++ b/tests/pnm3.testfile
@@ -0,0 +1,5 @@
+P3
+# CREATOR: GIMP PNM Filter Version 1.1
+10 20
+255
+255
--- a/tests/regex-eol.result
+++ b/tests/regex-eol.result
@@ -1 +1 @@
-Ansible Vault text, version 1.1, using AES256 encryption
\ No newline at end of file
+Ansible Vault text, version 1.1, using AES256 encryption
--- a/tests/test.c
+++ b/tests/test.c
@@ -27,6 +27,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 #include <errno.h>
 
@@ -51,34 +52,36 @@
 {
 	size_t len = 256;
 	int c;
-	char *l = (char *)xrealloc(NULL, len), *s = l;
+	char *l = xrealloc(NULL, len), *s = l;
 
 	for (c = getc(fp); c != EOF; c = getc(fp)) {
 		if (s == l + len) {
-			l = xrealloc(l, len * 2);
+			s = l + len;
 			len *= 2;
+			l = xrealloc(l, len);
 		}
 		*s++ = c;
 	}
 	if (s != l && s[-1] == '\n')
 		s--;
-	if (s == l + len)
-		l = (char *)xrealloc(l, len + 1);
+	if (s == l + len) {
+		l = xrealloc(l, len + 1);
+		s = l + len;
+	}
 	*s++ = '\0';
 
 	*final_len = s - l;
-	l = (char *)xrealloc(l, s - l);
-	return l;
+	return xrealloc(l, s - l);
 }
 
 int
 main(int argc, char **argv)
 {
-	struct magic_set *ms;
+	struct magic_set *ms = NULL;
 	const char *result;
 	size_t result_len, desired_len;
 	char *desired = NULL;
-	int e = EXIT_FAILURE;
+	int e = EXIT_FAILURE, flags, c;
 	FILE *fp;
 
 
@@ -88,7 +91,32 @@
 	else
 		prog = argv[0];
 
-	ms = magic_open(MAGIC_ERROR);
+	if (argc == 1)
+		return 0;
+
+	flags = 0;
+	while ((c = getopt(argc, argv, "ek")) != -1)
+		switch (c) {
+		case 'e':
+			flags |= MAGIC_ERROR;
+			break;
+		case 'k':
+			flags |= MAGIC_CONTINUE;
+			break;
+		default:
+			goto usage;
+		}
+
+	argc -= optind;
+	argv += optind;
+	if (argc != 2) {
+usage:
+		(void)fprintf(stderr,
+		    "Usage: %s [-ek] TEST-FILE RESULT\n", prog);
+		goto bad;
+	}
+
+	ms = magic_open(flags);
 	if (ms == NULL) {
 		(void)fprintf(stderr, "%s: ERROR opening MAGIC_NONE: %s\n",
 		    prog, strerror(errno));
@@ -100,29 +128,20 @@
 		goto bad;
 	}
 
-	if (argc == 1) {
-		e = 0;
-		goto bad;
-	}
-
-	if (argc != 3) {
-		(void)fprintf(stderr, "Usage: %s TEST-FILE RESULT\n", prog);
-		goto bad;
-	}
-	if ((result = magic_file(ms, argv[1])) == NULL) {
+	if ((result = magic_file(ms, argv[0])) == NULL) {
 		(void)fprintf(stderr, "%s: ERROR loading file %s: %s\n",
 		    prog, argv[1], magic_error(ms));
 		goto bad;
 	}
-	fp = fopen(argv[2], "r");
+	fp = fopen(argv[1], "r");
 	if (fp == NULL) {
 		(void)fprintf(stderr, "%s: ERROR opening `%s': %s",
-		    prog, argv[2], strerror(errno));
+		    prog, argv[1], strerror(errno));
 		goto bad;
 	}
 	desired = slurp(fp, &desired_len);
 	fclose(fp);
-	(void)printf("%s: %s\n", argv[1], result);
+	(void)printf("%s: %s\n", argv[0], result);
 	if (strcmp(result, desired) != 0) {
 	    result_len = strlen(result);
 	    (void)fprintf(stderr, "%s: ERROR: result was (len %zu)\n%s\n"
@@ -133,6 +152,7 @@
 	e = 0;
 bad:
 	free(desired);
-	magic_close(ms);
+	if (ms)
+		magic_close(ms);
 	return e;
 }
--- a/tests/uf2.result
+++ b/tests/uf2.result
@@ -1 +1 @@
-UF2 firmware image, family ESP32-S2, address 00000000, 4829 total blocks
\ No newline at end of file
+UF2 firmware image, family ESP32-S2, address 00000000, 4829 total blocks
--- a/tests/zstd-3-skippable-frames.result
+++ b/tests/zstd-3-skippable-frames.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 1
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 1
--- a/tests/zstd-dictionary-0.result
+++ b/tests/zstd-dictionary-0.result
@@ -1 +1 @@
-Zstandard dictionary (ID 0)
\ No newline at end of file
+Zstandard dictionary (ID 0)
--- a/tests/zstd-dictionary-1.result
+++ b/tests/zstd-dictionary-1.result
@@ -1 +1 @@
-Zstandard dictionary (ID 1)
\ No newline at end of file
+Zstandard dictionary (ID 1)
--- a/tests/zstd-dictionary-2.result
+++ b/tests/zstd-dictionary-2.result
@@ -1 +1 @@
-Zstandard dictionary (ID 285212672)
\ No newline at end of file
+Zstandard dictionary (ID 285212672)
--- a/tests/zstd-skippable-frame-0.result
+++ b/tests/zstd-skippable-frame-0.result
@@ -1 +1 @@
-Zstandard compressed data (v0.2)
\ No newline at end of file
+Zstandard compressed data (v0.2)
--- a/tests/zstd-skippable-frame-4.result
+++ b/tests/zstd-skippable-frame-4.result
@@ -1 +1 @@
-Zstandard compressed data (v0.3)
\ No newline at end of file
+Zstandard compressed data (v0.3)
--- a/tests/zstd-skippable-frame-8.result
+++ b/tests/zstd-skippable-frame-8.result
@@ -1 +1 @@
-Zstandard compressed data (v0.4)
\ No newline at end of file
+Zstandard compressed data (v0.4)
--- a/tests/zstd-skippable-frame-C.result
+++ b/tests/zstd-skippable-frame-C.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 1
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 1
--- a/tests/zstd-v0.2-FF.result
+++ b/tests/zstd-v0.2-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.2)
\ No newline at end of file
+Zstandard compressed data (v0.2)
--- a/tests/zstd-v0.3-FF.result
+++ b/tests/zstd-v0.3-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.3)
\ No newline at end of file
+Zstandard compressed data (v0.3)
--- a/tests/zstd-v0.4-FF.result
+++ b/tests/zstd-v0.4-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.4)
\ No newline at end of file
+Zstandard compressed data (v0.4)
--- a/tests/zstd-v0.5-FF.result
+++ b/tests/zstd-v0.5-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.5)
\ No newline at end of file
+Zstandard compressed data (v0.5)
--- a/tests/zstd-v0.6-FF.result
+++ b/tests/zstd-v0.6-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.6)
\ No newline at end of file
+Zstandard compressed data (v0.6)
--- a/tests/zstd-v0.7-00.result
+++ b/tests/zstd-v0.7-00.result
@@ -1 +1 @@
-Zstandard compressed data (v0.7), Dictionary ID: None
\ No newline at end of file
+Zstandard compressed data (v0.7), Dictionary ID: None
--- a/tests/zstd-v0.7-21.result
+++ b/tests/zstd-v0.7-21.result
@@ -1 +1 @@
-Zstandard compressed data (v0.7), Dictionary ID: 1
\ No newline at end of file
+Zstandard compressed data (v0.7), Dictionary ID: 1
--- a/tests/zstd-v0.7-22.result
+++ b/tests/zstd-v0.7-22.result
@@ -1 +1 @@
-Zstandard compressed data (v0.7), Dictionary ID: 513
\ No newline at end of file
+Zstandard compressed data (v0.7), Dictionary ID: 513
--- a/tests/zstd-v0.8-00.result
+++ b/tests/zstd-v0.8-00.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: None
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: None
--- a/tests/zstd-v0.8-01.result
+++ b/tests/zstd-v0.8-01.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 2
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 2
--- a/tests/zstd-v0.8-02.result
+++ b/tests/zstd-v0.8-02.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 770
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 770
--- a/tests/zstd-v0.8-03.result
+++ b/tests/zstd-v0.8-03.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 84148994
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 84148994
--- a/tests/zstd-v0.8-16.result
+++ b/tests/zstd-v0.8-16.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 770
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 770
--- a/tests/zstd-v0.8-20.result
+++ b/tests/zstd-v0.8-20.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: None
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: None
--- a/tests/zstd-v0.8-21.result
+++ b/tests/zstd-v0.8-21.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 1
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 1
--- a/tests/zstd-v0.8-22.result
+++ b/tests/zstd-v0.8-22.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 513
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 513
--- a/tests/zstd-v0.8-23.result
+++ b/tests/zstd-v0.8-23.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 67305985
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 67305985
--- a/tests/zstd-v0.8-F4.result
+++ b/tests/zstd-v0.8-F4.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: None
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: None
--- a/tests/zstd-v0.8-FF.result
+++ b/tests/zstd-v0.8-FF.result
@@ -1 +1 @@
-Zstandard compressed data (v0.8+), Dictionary ID: 67305985
\ No newline at end of file
+Zstandard compressed data (v0.8+), Dictionary ID: 67305985
