...
 
Commits (12)
#
# Build ignores
#
.*
*.o
*.o.*
*.a
*.s
*.1.gz
Kbuild
Config.in
#
# Never ignore these
#
!.gitignore
#
# Normal output and testing dirs
#
/foo
/fsck.winregfs
/mount.winregfs
/debug.log
/*.?.gz
#
# Backups / patches
#
*~
*.orig
*.rej
/*.patch
#
# debugging stuff
#
core
.gdb_history
.gdbinit
*.hiv
Just type "make" and then "make install".
DESTDIR may be specified to install elsewhere: make DESTDIR=/pkg install
If your compiler doesn't support LTO, remove "-flto" from Makefile and try
compiling again. ntreg still contains code that winregfs may not use and LTO
removes this dead code from the final program.
A script "chroot_build.sh" is provided which will perform builds in your own
local chroot build environments and makes tar.xz package files for each one
specified at the top of the script. This is handy for supporting multiple C
libraries and varying machine bit sizes.
This diff is collapsed.
This diff is collapsed.
CC=gcc
CFLAGS=-O2 -g
#CFLAGS=-O2 -flto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables
#CFLAGS=-Og -g3
BUILD_CFLAGS = -std=gnu99 -I. -D_FILE_OFFSET_BITS=64 -pipe -fstrict-aliasing
#BUILD_CFLAGS += -Wall -Wextra -Wstrict-aliasing -Wcast-align -pedantic -Wno-unused-parameter
BUILD_CFLAGS += -Wall -Wextra -Wwrite-strings -Wcast-align -Wstrict-aliasing -pedantic -Wstrict-overflow -Wstrict-prototypes -Wpointer-arith -Wundef
BUILD_CFLAGS += -Wshadow -Wfloat-equal -Wstrict-overflow=5 -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wunreachable-code -Wformat=2 -Winit-self
#LDFLAGS=-s
#LDFLAGS=-flto -s -Wl,--gc-sections
LDFLAGS=
FUSE_CFLAGS=$(shell pkg-config fuse --cflags)
FUSE_LDFLAGS=$(shell pkg-config fuse --libs)
FUSE_LIBS=-lfuse
prefix=/usr
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
mandir=${prefix}/man
datarootdir=${prefix}/share
datadir=${datarootdir}
sysconfdir=${prefix}/etc
OBJS_LIB=ntreg.o jody_string.o
OBJS_FSCK=fsck_winregfs.o $(OBJS_LIB)
OBJS_MOUNT=winregfs.o jody_hash.o $(OBJS_LIB)
BUILD_CFLAGS += $(CFLAGS_EXTRA)
all: mount.winregfs fsck.winregfs manual
mount.winregfs: $(OBJS_MOUNT)
$(CC) $(CFLAGS) $(LDFLAGS) $(FUSE_CFLAGS) $(BUILD_CFLAGS) $(FUSE_LDFLAGS) -o mount.winregfs $(OBJS_MOUNT) $(FUSE_LIBS)
fsck.winregfs: $(OBJS_FSCK)
$(CC) $(CFLAGS) $(LDFLAGS) $(FUSE_CFLAGS) $(BUILD_CFLAGS) $(FUSE_LDFLAGS) -o fsck.winregfs $(OBJS_FSCK)
manual:
gzip -9 < mount.winregfs.8 > mount.winregfs.8.gz
gzip -9 < fsck.winregfs.8 > fsck.winregfs.8.gz
.c.o:
$(CC) -c $(BUILD_CFLAGS) $(FUSE_CFLAGS) $(CFLAGS) $<
clean:
rm -f *.o *~ mount.winregfs fsck.winregfs debug.log *.?.gz
distclean:
rm -f *.o *~ mount.winregfs fsck.winregfs debug.log *.?.gz winregfs*.pkg.tar.*
install: all
install -D -o root -g root -m 0644 mount.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/mount.winregfs.8.gz
install -D -o root -g root -m 0644 fsck.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/fsck.winregfs.8.gz
install -D -o root -g root -m 0755 -s mount.winregfs $(DESTDIR)/$(bindir)/mount.winregfs
install -D -o root -g root -m 0755 -s fsck.winregfs $(DESTDIR)/$(bindir)/fsck.winregfs
package:
+./chroot_build.sh
THE WINDOWS REGISTRY FUSE FILESYSTEM
====================================
If you have any questions, comments, or patches, send me an email:
jody@jodybruchon.com
One of the most difficult things to deal with in years of writing Linux
utilities to work with and repair Windows PCs is the Windows registry.
While many excellent tools exist to work with NTFS filesystems and to change
and remove passwords from user accounts, the ability to work with the
registry has always been severely lacking. Included in the excellent chntpw
package is a primitive registry editor "reged" which has largely been quite
helpful and I have been grateful for its existence, but it suffers from a
very limited interface and a complete lack of scriptability that presents a
major hurdle for anyone wanting to do more with the registry than wipe out a
password or change the "Start" flag of a system service.
Because of the serious limitations of "reged," the only practical way to do
anything registry-oriented with a shell script was to export an ENTIRE HIVE
to a .reg file, crudely parse the file for what you want, create a .reg file
from the script to import the changes, and import them. Needless to say, the
process is slow, complicated, and frustrating. I even wrote a tool called
"read_inf_section" to help my scripts parse INF/INI/REG files faster because
of this need (but also for an unrelated need to read .inf files from driver
packages.) This complexity became too excessive, so I came up with a much
better way to tweak the registry from shell scripts and programs.
Thus, the Windows Registry FUSE Filesystem "winregfs" was born. chntpw
( http://pogostick.net/~pnh/ntpasswd/ ) has an excellent library for
working with Windows NT registry hive files, distributed under the LGPL.
winregfs is essentially a glue layer between ntreg.c and FUSE, translating
Windows registry keys and values into ordinary directories and files.
Features include:
* Full write support (value size limited to 8192 bytes)
* Case-insensitivity in key/value name matching
* Automatic forward-slash escaping (gets around the Linux pathname limitation)
* "Wildcard" name matching on reads, i.e. "cat foo/bar" matches "foo/bar.sz"
* Friendly DWORD editing in hexadecimal ASCII text rather than raw data
Also included is a tool called "fsck.winregfs" which will perform a basic check
of the integrity of a registry hive. It recursively follows all possible keys
and values, checking for errors in offsets, reading data, and value types. To
use it, type "fsck.winregfs [hivename]" and when the scan completes a detailed
list of statistics and error counts will be produced. The exit status can be
checked (i.e. in a script) for success or failure of the check.
A few keys and value names in the Windows registry such as MIME types contain
forward slash characters; winregfs substitutes "_SLASH_" where a forward
slash appears in names.
To use winregfs, make a directory to mount on and point it to the registry
hive of interest:
---
$ mkdir reg
$ mount.winregfs /mnt/sdc2/Windows/System32/config/software reg/
---
Now, you can see everything in that hive under "reg":
---
$ ls reg
7-Zip/ Google/ Policies/
AVAST Software/ InstalledOptions/ Program Groups/
Adobe/ Intel/ RegisteredApplications/
Analog Devices/ LibreOffice/ S3/
C07ft5Y/ Macromedia/ Schlumberger/
Classes/ Microsoft/ Secure/
Clients/ Mozilla/ Sigmatel/
Diskeeper Corporation/ MozillaPlugins/ The Document Foundation/
GNU/ NVIDIA Corporation/ Windows 3.1 Migration Status/
Gabest/ ODBC/ mozilla.org/
Gemplus/ Piriform/
---
Let's say you want to see some things that automatically run during startup.
---
$ ls -l reg/Microsoft/Windows/CurrentVersion/Run
total 0
-r--r--r-- 1 root root 118 Dec 31 1969 Adobe ARM.sz
-r--r--r-- 1 root root 124 Dec 31 1969 DiskeeperSystray.sz
-r--r--r-- 1 root root 60 Dec 31 1969 HotKeysCmds.sz
-r--r--r-- 1 root root 66 Dec 31 1969 IgfxTray.sz
-r--r--r-- 1 root root 70 Dec 31 1969 KernelFaultCheck.esz
-r--r--r-- 1 root root 66 Dec 31 1969 Persistence.sz
-r--r--r-- 1 root root 100 Dec 31 1969 SoundMAXPnP.sz
-r--r--r-- 1 root root 118 Dec 31 1969 avast.sz
---
You want to see what these values contain.
---
$ for X in reg/Microsoft/Windows/CurrentVersion/Run/*
> do echo -en "$X\n "; cat "$X"; echo; done
reg/Microsoft/Windows/CurrentVersion/Run/Adobe ARM.sz
"C:\Program Files\Common Files\Adobe\ARM\1.0\AdobeARM.exe"
reg/Microsoft/Windows/CurrentVersion/Run/DiskeeperSystray.sz
"C:\Program Files\Diskeeper Corporation\Diskeeper\DkIcon.exe"
reg/Microsoft/Windows/CurrentVersion/Run/HotKeysCmds.sz
C:\WINDOWS\system32\hkcmd.exe
reg/Microsoft/Windows/CurrentVersion/Run/IgfxTray.sz
C:\WINDOWS\system32\igfxtray.exe
reg/Microsoft/Windows/CurrentVersion/Run/KernelFaultCheck.esz
%systemroot%\system32\dumprep 0 -k
reg/Microsoft/Windows/CurrentVersion/Run/Persistence.sz
C:\WINDOWS\system32\igfxpers.exe
reg/Microsoft/Windows/CurrentVersion/Run/SoundMAXPnP.sz
C:\Program Files\Analog Devices\Core\smax4pnp.exe
reg/Microsoft/Windows/CurrentVersion/Run/avast.sz
"C:\Program Files\AVAST Software\Avast\avastUI.exe" /nogui
---
Has anything hijacked the Windows "shell" value that runs explorer.exe?
---
$ cat reg/Microsoft/Windows\ NT/CurrentVersion/Winlogon/Shell.sz
Explorer.exe
---
How about the userinit.exe value?
---
$ cat reg/Microsoft/Windows\ NT/CurrentVersion/Winlogon/Userinit.sz
C:\WINDOWS\system32\userinit.exe,
---
Perhaps check if some system policies are set (note that REG_DWORD values now
work as friendly hexadecimal text files instead of raw data):
---
$ cat \
> reg/Policies/Microsoft/Windows/System/Allow-LogonScript-NetbiosDisabled.dw
00000001
You can probably figure out what to do with it from here. ;-)
LICENSING NOTICE
----------------
ntreg.c and ntreg.h are distributed under the terms of the LGPL as described
in LGPL.txt while all other winregfs components are licensed under the terms
of the GNU GPL as described in LICENSE.
Windows Registry FUSE Filesystem TODO list
------------------------------------------
* Fix 8 KiB file write limit issue (may really be in ntreg.c)
For now an error is issued on attempts to write >8192 bytes
since there are extremely few values that contain this much
data; the XP compatibility shim cache is pretty much the
only value of such a size (all others are <6000 bytes)
* Allow arbitrary value types using a hexadecimal extension
(used in SAM and some MS Click-to-Run registry keys)
* Unicode and non-ASCII character support
This is not only useful for non-Latin characters, it also
can be used to find novel registry-resident malware such as
Poweliks, which uses a non-ASCII name to block the Windows
registry editor from being able to touch it.
#!/bin/sh
# Jody's generic chroot build script
# Version 1.0
ARCHES="i386 x86-64 uclibc-i386 uclibc-x86-64"
test -z "$NAME" && NAME="$(basename "$(pwd)")"
test -e "version.h" && VER="$(grep '#define VER ' version.h | tr -d \\\" | cut -d' ' -f3)"
test -z "$VER" && VER=0
export NAME
export VER
export CHROOT_BASE=/chroots
export WD="$(pwd)"
export PKG="pkg"
echo "chroot builder: building '$NAME' version '$VER'"
trap clean_exit INT QUIT ABRT HUP
clean_exit () {
umount $CHROOT/proc $CHROOT/sys $CHROOT/tmp $CHROOT/dev $CHROOT/usr/src $CHROOT/home
}
do_build () {
test -z "$WD" && echo "WD not set, aborting" && exit 1
test -z "$PKG" && echo "PKG not set, aborting" && exit 1
make clean
if ! make -j$JOBS all
then echo "Build failed"; exit 1
else
echo "WD/PKG: $WD/$PKG"
test -d $WD/$PKG && rm -rf $WD/$PKG
mkdir $WD/$PKG
make DESTDIR=$WD/$PKG install && \
tar -C pkg -c usr | xz -e > ${NAME}_$VER-$ARCH.pkg.tar.xz
fi
}
if [ "$(id -u)" != "0" ]
then echo "You must be root to auto-build chroot packages."
exit 1
fi
if [ "$DO_CHROOT_BUILD" = "1" ]
then
test -z "$1" && echo "No arch specified" && exit 1
test ! -d "$1" && echo "Not a directory: $1" && exit 1
cd $1
export WD="$1"
do_build
echo "finished: $1"
exit
else
echo baz
export DO_CHROOT_BUILD=1
for ARCH in $ARCHES
do
export ARCH
export CHROOT="$CHROOT_BASE/$ARCH"
test ! -d $CHROOT && echo "$CHROOT not present, not building $ARCH package." && continue
echo "Performing package build for $CHROOT"
test ! -x $CHROOT/bin/sh && echo "$CHROOT does not seem to be a chroot; aborting." && exit 1
mount --bind /dev $CHROOT/dev || clean_exit
mount --bind /usr/src $CHROOT/usr/src || clean_exit
mount --bind /home $CHROOT/home || clean_exit
mount -t proc proc $CHROOT/proc || clean_exit
mount -t sysfs sysfs $CHROOT/sys || clean_exit
mount -t tmpfs tmpfs $CHROOT/tmp || clean_exit
if echo "$ARCH" | grep -q "i386"
then linux32 chroot $CHROOT $WD/$0 $WD
else chroot $CHROOT $WD/$0 $WD
fi
umount $CHROOT/proc $CHROOT/sys $CHROOT/tmp $CHROOT/dev $CHROOT/usr/src $CHROOT/home
test -d $WD/$PKG && rm -rf $WD/$PKG
done
fi
#ifndef CONFIG_H
#define CONFIG_H
/* Threaded mode suffers from decreased performance */
#define ENABLE_THREADED 0
#define ENABLE_LOGGING 0
#define ENABLE_DEBUG_LOGGING 0
#define ENABLE_DEBUG_PRINTF 0
#define ENABLE_NKOFS_CACHE 1
#define ENABLE_NKOFS_CACHE_STATS 0
#define NKOFS_CACHE_ITEMS 64
#endif /* CONFIG_H */
winregfs (0.7-2) unstable; urgency=medium
[ Raphaël Hertzog ]
* Update team maintainer address to Debian Security Tools
<team+pkg-security@tracker.debian.org>
* Update Vcs-Git and Vcs-Browser for the move to salsa.debian.org
[ Giovani Augusto Ferreira ]
* Bumped DH level to 11
* Bumped Standards-Version to 4.1.4
* debian/copyright: updated copyright years
* debian/patches/cross.patch: fix FTCBFS (Closes: #900741)
- Allow substituting pkg-config and install.
- Pass an install that never strips.
- Thanks to Helmut Grohne <helmut@subdivi.de> for the patch.
-- Giovani Augusto Ferreira <giovani@debian.org> Sun, 24 Jun 2018 18:14:28 -0300
winregfs (0.7-1) unstable; urgency=medium
* New upstream release.
* Updated my email address.
* debian/control:
- Bumped Standards-Version to 4.0.0.
* debian/copyright: updated the packaging and copyright years.
* debian/patches/fix-install.patch:
- Updated, according to the new release.
-- Giovani Augusto Ferreira <giovani@debian.org> Sat, 24 Jun 2017 15:44:36 -0300
winregfs (0.6-1) unstable; urgency=medium
* Initial release (Closes: #840907)
-- Giovani Augusto Ferreira <giovani@riseup.net> Sat, 15 Oct 2016 15:42:21 -0300
Source: winregfs
Section: utils
Priority: optional
Maintainer: Debian Security Tools <team+pkg-security@tracker.debian.org>
Uploaders: Giovani Augusto Ferreira <giovani@debian.org>
Build-Depends: debhelper (>= 11), libfuse-dev, pkg-config
Standards-Version: 4.1.4
Homepage: https://github.com/jbruchon/winregfs
Vcs-Git: https://salsa.debian.org/pkg-security-team/winregfs.git
Vcs-Browser: https://salsa.debian.org/pkg-security-team/winregfs
Package: winregfs
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: Windows registry FUSE filesystem
Winregfs is a FUSE-based filesystem driver that enables accessing of Windows
registry hive files as ordinary filesystems. Registry hive file editing can
be performed with ordinary shell scripts and command-line tools once mounted.
.
fsck.winregfs scans a Windows registry hive file for problems that indicate
the hive has been damaged by hardware or software issues, reading recursively
the key and value data structures in the registry hive.
.
This package provides mount.winregfs and fsck.winregfs commands.
Winregfs is useful for pentesters, ethical hackers and forensics experts.
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: winregfs
Source: https://github.com/jbruchon/winregfs
Files: *
Copyright: 2014-2017 Jody Bruchon <jody@jodybruchon.com>
License: GPL-2
Files: jody_hash.c
Copyright: 2014-2017 Jody Bruchon <jody@jodybruchon.com>
License: Expat
Files:ntreg.c
ntreg.h
Copyright: 1997-2014 Petter Nordahl-Hagen
2014 Jody Bruchon <jody@jodybruchon.com>
License: LGPL-2.1
Files: debian/*
Copyright: 2016-2018 Giovani Augusto Ferreira <giovani@debian.org>
License: BSD-3-Clause
License: GPL-2
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
License: LGPL-2.1
This package is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; version
2.1 of the License.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU Lesser General
Public License can be found in "/usr/share/common-licenses/LGPL-2.1".
License: Expat
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
License: BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Description: Fix fail to cross build from source.
Author: Helmut Grohne <helmut@subdivi.de>
Last-Update: 2018-06-03
Index: winregfs/Makefile
===================================================================
--- winregfs.orig/Makefile
+++ winregfs/Makefile
@@ -1,4 +1,6 @@
CC=gcc
+INSTALL?=install
+PKG_CONFIG?=pkg-config
CFLAGS+=-O2 -g -fPIE
#CFLAGS=-O2 -flto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables
#CFLAGS=-Og -g3
@@ -9,8 +11,8 @@ BUILD_CFLAGS += -Wshadow -Wfloat-equal -
LDFLAGS+=-s -pie
#LDFLAGS=-flto -s -Wl,--gc-sections
#LDFLAGS=
-FUSE_CFLAGS=$(shell pkg-config fuse --cflags)
-FUSE_LDFLAGS=$(shell pkg-config fuse --libs)
+FUSE_CFLAGS=$(shell $(PKG_CONFIG) fuse --cflags)
+FUSE_LDFLAGS=$(shell $(PKG_CONFIG) fuse --libs)
FUSE_LIBS=-lfuse
prefix=/usr
@@ -49,10 +51,10 @@ distclean:
rm -f *.o *~ mount.winregfs fsck.winregfs debug.log *.?.gz winregfs*.pkg.tar.*
install: all
- install -D -o root -g root -m 0644 mount.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/mount.winregfs.8.gz
- install -D -o root -g root -m 0644 fsck.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/fsck.winregfs.8.gz
- install -D -o root -g root -m 0755 -s mount.winregfs $(DESTDIR)/$(bindir)/mount.winregfs
- install -D -o root -g root -m 0755 -s fsck.winregfs $(DESTDIR)/$(bindir)/fsck.winregfs
+ $(INSTALL) -D -o root -g root -m 0644 mount.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/mount.winregfs.8.gz
+ $(INSTALL) -D -o root -g root -m 0644 fsck.winregfs.8.gz $(DESTDIR)/$(mandir)/man8/fsck.winregfs.8.gz
+ $(INSTALL) -D -o root -g root -m 0755 -s mount.winregfs $(DESTDIR)/$(bindir)/mount.winregfs
+ $(INSTALL) -D -o root -g root -m 0755 -s fsck.winregfs $(DESTDIR)/$(bindir)/fsck.winregfs
package:
+./chroot_build.sh
Description: Fix install path to manpages and add GCC hardening.
Author: Giovani Augusto Ferreira <giovani@debian.org>
Last-Update: 2017-06-24
Index: winregfs-0.7/Makefile
===================================================================
--- winregfs-0.7.orig/Makefile
+++ winregfs-0.7/Makefile
@@ -1,14 +1,14 @@
CC=gcc
-CFLAGS=-O2 -g
+CFLAGS+=-O2 -g -fPIE
#CFLAGS=-O2 -flto -ffunction-sections -fdata-sections -fno-unwind-tables -fno-asynchronous-unwind-tables
#CFLAGS=-Og -g3
BUILD_CFLAGS = -std=gnu99 -I. -D_FILE_OFFSET_BITS=64 -pipe -fstrict-aliasing
#BUILD_CFLAGS += -Wall -Wextra -Wstrict-aliasing -Wcast-align -pedantic -Wno-unused-parameter
BUILD_CFLAGS += -Wall -Wextra -Wwrite-strings -Wcast-align -Wstrict-aliasing -pedantic -Wstrict-overflow -Wstrict-prototypes -Wpointer-arith -Wundef
BUILD_CFLAGS += -Wshadow -Wfloat-equal -Wstrict-overflow=5 -Waggregate-return -Wcast-qual -Wswitch-default -Wswitch-enum -Wunreachable-code -Wformat=2 -Winit-self
-#LDFLAGS=-s
+LDFLAGS+=-s -pie
#LDFLAGS=-flto -s -Wl,--gc-sections
-LDFLAGS=
+#LDFLAGS=
FUSE_CFLAGS=$(shell pkg-config fuse --cflags)
FUSE_LDFLAGS=$(shell pkg-config fuse --libs)
FUSE_LIBS=-lfuse
@@ -16,7 +16,7 @@ FUSE_LIBS=-lfuse
prefix=/usr
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
-mandir=${prefix}/man
+mandir=${prefix}/share/man
datarootdir=${prefix}/share
datadir=${datarootdir}
sysconfdir=${prefix}/etc
@@ -40,7 +40,7 @@ manual:
gzip -9 < fsck.winregfs.8 > fsck.winregfs.8.gz
.c.o:
- $(CC) -c $(BUILD_CFLAGS) $(FUSE_CFLAGS) $(CFLAGS) $<
+ $(CC) -c $(BUILD_CFLAGS) $(FUSE_CFLAGS) $(CFLAGS) $(CPPFLAGS) $<
clean:
rm -f *.o *~ mount.winregfs fsck.winregfs debug.log *.?.gz
fix-install.patch
cross.patch
#!/usr/bin/make -f
#export DH_VERBOSE = 1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
%:
dh $@
override_dh_auto_install:
dh_auto_install -- INSTALL='install --strip-program=true'
version=4
https://github.com/jbruchon/winregfs/releases .*/archive/(?:release|v)?-?(\d\S+)\.tar\.(?:bz2|gz|xz)
.\" Copyright (c) 2014-2017 Jody Bruchon
.\" Licensed under the GNU General Public License v2
.\"
.TH winregfs 8 "20 May 2014" "fsck.winregfs"
.SH NAME
fsck.winregfs \- Check a Windows registry file
.SH SYNOPSIS
.B fsck.winregfs
.I [-v] hivefile
.SH DESCRIPTION
\fBfsck.winregfs\fP scans a Windows registry hive file for problems that
indicate the hive has been damaged by hardware or software issues. If the
\fI-v\fP option is specified, the program will output detailed information
about the problems it finds.
.SH LIMITATIONS
\fBfsck.winregfs\fP works by recursively reading the key and value data
structures in the registry hive. Currently it does not read the actual data
stored in a value, and due to the nature of the ntreg library's interfaces
the checks are currently limited to reporting that errors exist; the details
of the error conditions encountered are not broken down in the final output.
.SH SEE ALSO
.BR mount.winregfs (8)
/*
* Windows registry "filesystem checker"
* Reads all the keys in a hive and reports any errors triggered
*
* Copyright (C) 2014-2017 by Jody Bruchon <jody@jodybruchon.com>
*
* Licensed under GNU GPL v2. See LICENSE and README for details.
*
*/
#define FSCK_WINREGFS
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libgen.h>
#include "ntreg.h"
#include "jody_string.h"
#include "winregfs.h"
#define UPDATE_INTERVAL 300
struct winregfs_data wd;
struct fsck_stat {
int e_travpath;
int e_nkofs;
int e_read_key;
int e_read_val;
int w_type;
int keys;
int values;
int maxdepth;
int update_delay;
};
void invalidate_nk_cache(void) {
return;
}
/* Converts a path to the required formats for keypath/nodepath usage */
static inline int sanitize_path(const char * const restrict path,
char * const restrict keypath,
char * const restrict node)
{
strncpy(keypath, path, ABSPATHLEN);
strncpy(node, path, ABSPATHLEN);
dirname(keypath); /* need to read the root key */
strncpy(node, basename(node), ABSPATHLEN);
return EXIT_SUCCESS;
}
void show_progress(struct fsck_stat * const restrict stats) {
if (stats->update_delay > 0) {
stats->update_delay--;
return;
} else stats->update_delay = UPDATE_INTERVAL;
printf("Keys: %d Values: %d \r",
stats->keys, stats->values);
return;
}
static int process_key(struct fsck_stat * const restrict stats,
const char * const restrict path,
int depth, int verbose)
{
/*
* For keys, run process_key again recursively
* For values, just check that the value exists for now
*/
struct nk_key *key;
int nkofs, i;
struct ex_data ex;
struct vex_data vex;
int count = 0, countri = 0, error_count = 0;
char filename[ABSPATHLEN];
char keypath[ABSPATHLEN];
depth++;
if (stats->maxdepth < depth) stats->maxdepth = depth;
stats->keys++;
show_progress(stats);
strncpy(keypath, path, ABSPATHLEN);
nkofs = trav_path(wd.hive, 0, keypath, TPF_NK_EXACT);
if (!nkofs) {
if (verbose) printf("\rPath traversal failure: %s\n", keypath);
stats->e_travpath++;
return -1;
}
nkofs += 4;
if(nkofs > wd.hive->size) {
if (verbose) printf("\rNK offset too large: %s\n", keypath);
stats->e_nkofs++;
return -1;
}
key = (struct nk_key *)(wd.hive->buffer + nkofs);
if (key->no_subkeys) {
while ((i = ex_next_n(wd.hive, nkofs, &count, &countri, &ex)) > 0) {
strncpy(filename, keypath, ABSPATHLEN);
if(strncmp(keypath, "\\", 3)) strncat(filename, "\\", ABSPATHLEN);
strncat(filename, ex.name, ABSPATHLEN);
error_count += process_key(stats, filename, depth, verbose);
}
if (i < 0) {
if (verbose) printf("\rKey read failure: %s\n", keypath);
stats->e_read_key++;
show_progress(stats);
}
}
count = 0;
if (key->no_values) {
while ((i = ex_next_v(wd.hive, nkofs, &count, &vex)) > 0) {
stats->values++;
show_progress(stats);
if (vex.type > REG_MAX) {
if (verbose) printf("\rValue type 0x%x is an unknown type: %s\n", vex.type, keypath);
stats->w_type++;
}
strncpy(filename, keypath, ABSPATHLEN);
strncat(filename, "\\", ABSPATHLEN);
if (strlen(vex.name) == 0) strncpy(filename, "@", 2);
else strncat(filename, vex.name, ABSPATHLEN);
}
if (i < 0) {
if (verbose) printf("\rValue read failure: %s\n", keypath);
stats->e_read_val++;
show_progress(stats);
}
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
char file[ABSPATHLEN];
char path[ABSPATHLEN];
int error_count, warn_count, verbose = 0;
struct fsck_stat stats;
if (argc == 2 && !strcaseeq(argv[1], "-v")) {
fprintf(stderr, "Windows Registry Hive File Checker %s (%s)\n", VER, VERDATE);
return EXIT_SUCCESS;
}
if ((argc < 2) || (argv[argc-1][0] == '-')) {
fprintf(stderr, "Windows Registry Hive File Checker %s (%s)\n", VER, VERDATE);
fprintf(stderr, "\nUsage: %s [options] hivename\n\n", argv[0]);
return EXIT_FAILURE;
}
if (!strncmp(argv[1], "-v", 3)) {
printf("Verbose mode enabled\n");
verbose = 1;
}
/* Pull hive file name from command line */
strncpy(file, argv[argc-1], ABSPATHLEN);
/* malloc() and initialize cache pointers/data */
wd.hive = open_hive(file, HMODE_RW);
if (!wd.hive) {
fprintf(stderr, "Error: couldn't open %s\n", file);
return EXIT_FAILURE;
}
stats.e_travpath = 0;
stats.e_nkofs = 0;
stats.e_read_key = 0;
stats.e_read_val = 0;
stats.w_type = 0;
stats.keys = 0;
stats.values = 0;
stats.maxdepth = 0;
stats.update_delay = 0;
/* Start at the hive root */
path[0] = '\\'; path[1] = '\0';
process_key(&stats, path, -1, verbose);
close_hive(wd.hive);
error_count = (stats.e_travpath +
stats.e_nkofs +
stats.e_read_key +
stats.e_read_val);
warn_count = (stats.w_type);
/* Show final stats for everything */
printf("Keys: %d Values: %d Max key depth: %d\n", stats.keys, stats.values, stats.maxdepth);
if (stats.e_travpath)
printf("\nPath traversal errors: %d\n", stats.e_travpath);
if (stats.e_nkofs)
printf("\n'nk' offset errors: %d\n", stats.e_nkofs);
if (stats.e_read_key)
printf("\nKey read errors: %d\n", stats.e_read_key);
if (stats.e_read_val)
printf("\nValue read errors: %d\n", stats.e_read_val);
if (stats.w_type)
printf("\nValue type warnings: %d\n", stats.w_type);
if (error_count || warn_count) {
printf("\nHive %s has ", file);
if (error_count) {
printf("%d total errors", error_count);
if (warn_count) printf(" and ");
}
if (warn_count) printf("%d total warnings", warn_count);
printf("\n\n");
} else printf("Hive %s is clean.\n\n", file);
return (error_count ? EXIT_FAILURE : EXIT_SUCCESS);
}
/* Jody Bruchon's fast hashing function
*
* This function was written to generate a fast hash that also has a
* fairly low collision rate. The collision rate is much higher than
* a secure hash algorithm, but the calculation is drastically simpler
* and faster.
*
* Copyright (C) 2014-2017 by Jody Bruchon <jody@jodybruchon.com>
* Released under The MIT License
*/
#include <stdio.h>
#include <stdlib.h>
#include "jody_hash.h"
/* DO NOT modify the shift unless you know what you're doing.
* This shift was decided upon after lots of testing and
* changing it will likely cause lots of hash collisions. */
#ifndef JODY_HASH_SHIFT
#define JODY_HASH_SHIFT 11
#endif
/* The salt value's purpose is to cause each byte in the
* hash_t word to have a positionally dependent variation.
* It is injected into the calculation to prevent a string of
* identical bytes from easily producing an identical hash. */
/* The tail mask table is used for block sizes that are
* indivisible by the width of a hash_t. It is ANDed with the
* final hash_t-sized element to zero out data in the buffer
* that is not part of the data to be hashed. */
/* Set hash parameters based on requested hash width */
#if JODY_HASH_WIDTH == 64
#define JODY_HASH_CONSTANT 0x1f3d5b79U
static const hash_t tail_mask[] = {
0x0000000000000000,
0x00000000000000ff,
0x000000000000ffff,
0x0000000000ffffff,
0x00000000ffffffff,
0x000000ffffffffff,
0x0000ffffffffffff,
0x00ffffffffffffff,
0xffffffffffffffff
};
#endif /* JODY_HASH_WIDTH == 64 */
#if JODY_HASH_WIDTH == 32
#define JODY_HASH_CONSTANT 0x1f3d5b79U
static const hash_t tail_mask[] = {
0x00000000,
0x000000ff,
0x0000ffff,
0x00ffffff,
0xffffffff,
};
#endif /* JODY_HASH_WIDTH == 32 */
#if JODY_HASH_WIDTH == 16
#define JODY_HASH_CONSTANT 0x1f5bU
static const hash_t tail_mask[] = {
0x0000,
0x00ff,
0xffff,
};
#endif /* JODY_HASH_WIDTH == 16 */
/* Hash a block of arbitrary size; must be divisible by sizeof(hash_t)
* The first block should pass a start_hash of zero.
* All blocks after the first should pass start_hash as the value
* returned by the last call to this function. This allows hashing
* of any amount of data. If data is not divisible by the size of
* hash_t, it is MANDATORY that the caller provide a data buffer
* which is divisible by sizeof(hash_t). */
extern hash_t jody_block_hash(const hash_t * restrict data,
const hash_t start_hash, const size_t count)
{
hash_t hash = start_hash;
hash_t element;
hash_t partial_salt;
size_t len;
/* Don't bother trying to hash a zero-length block */
if (count == 0) return hash;
len = count / sizeof(hash_t);
for (; len > 0; len--) {
element = *data;
hash += element;
hash += JODY_HASH_CONSTANT;
hash = (hash << JODY_HASH_SHIFT) | hash >> (sizeof(hash_t) * 8 - JODY_HASH_SHIFT);
hash ^= element;
hash = (hash << JODY_HASH_SHIFT) | hash >> (sizeof(hash_t) * 8 - JODY_HASH_SHIFT);
hash ^= JODY_HASH_CONSTANT;
hash += element;
data++;
}
/* Handle data tail (for blocks indivisible by sizeof(hash_t)) */
len = count & (sizeof(hash_t) - 1);
if (len) {
partial_salt = JODY_HASH_CONSTANT & tail_mask[len];
element = *data & tail_mask[len];
hash += element;
hash += partial_salt;
hash = (hash << JODY_HASH_SHIFT) | hash >> (sizeof(hash_t) * 8 - JODY_HASH_SHIFT);
hash ^= element;
hash = (hash << JODY_HASH_SHIFT) | hash >> (sizeof(hash_t) * 8 - JODY_HASH_SHIFT);
hash ^= partial_salt;
hash += element;
}
return hash;
}
/* Jody Bruchon's fast hashing function (headers)
* See jody_hash.c for license information */
#ifndef JODY_HASH_H
#define JODY_HASH_H
#ifdef __cplusplus
extern "C" {
#endif
/* Required for uint64_t */
#include <stdint.h>
/* Width of a jody_hash. Changing this will also require
* changing the width of tail masks and endian conversion */
#ifndef JODY_HASH_WIDTH
#define JODY_HASH_WIDTH 64
#endif
#if JODY_HASH_WIDTH == 64
typedef uint64_t hash_t;
#endif
#if JODY_HASH_WIDTH == 32
typedef uint32_t hash_t;
#endif
#if JODY_HASH_WIDTH == 16
typedef uint16_t hash_t;
#endif
/* Version increments when algorithm changes incompatibly */
#define JODY_HASH_VERSION 4
extern hash_t jody_block_hash(const hash_t * restrict data,
const hash_t start_hash, const size_t count);
#ifdef __cplusplus
}
#endif
#endif /* JODY_HASH_H */
/*
* Jody Bruchon's string function library <jody@jodybruchon.com>
* Copyright (C) 2015-2017
* Distributed under the GNU General Public License version 2
*/
#include <stdint.h>
#include <unistd.h>
/* Like strncasecmp() but only tests for equality */
extern int strncaseeq(const char *s1, const char *s2, size_t len)
{
size_t i = 0;
while (i < len) {
if (*s1 != *s2) {
unsigned char c1, c2;
c1 = *(const unsigned char *)s1;
c2 = *(const unsigned char *)s2;
/* Transform upper case to lower case */
if (c1 == 0 || c2 == 0) return 1;
if (c1 >= 'A' && c1 <= 'Z') c1 |= 0x20;
if (c2 >= 'A' && c2 <= 'Z') c2 |= 0x20;
if (c1 != c2) return 1;
} else {
if (*s1 == 0) return 0;
}
s1++; s2++;
i++;
}
return 0;
}
/* Like strcasecmp() but only tests for equality */
extern int strcaseeq(const char *s1, const char *s2)
{
while (1) {
if (*s1 != *s2) {
unsigned char c1, c2;
c1 = *(const unsigned char *)s1;
c2 = *(const unsigned char *)s2;
/* Transform upper case to lower case */
if (c1 == 0 || c2 == 0) return 1;
if (c1 >= 'A' && c1 <= 'Z') c1 |= 0x20;
if (c2 >= 'A' && c2 <= 'Z') c2 |= 0x20;
if (c1 != c2) return 1;
} else {
if (*s1 == 0) return 0;
}
s1++; s2++;
}
return 1;
}
/* Like strncmp() but only tests for equality */
extern int strneq(const char *s1, const char *s2, size_t len)
{
size_t i = 0;
if (!len) return 0;
while (*s1 != '\0' && *s2 != '\0') {
if (*s1 != *s2) return 1;
s1++; s2++; i++;
if (i == len) return 0;
}
if (*s1 != *s2) return 1;
return 0;
}
/* Like strcmp() but only tests for equality */
extern int streq(const char *s1, const char *s2)
{
while (*s1 != '\0' && *s2 != '\0') {
if (*s1 != *s2) return 1;
s1++; s2++;
}
if (*s1 != *s2) return 1;
return 0;
}
/*
* Jody Bruchon's string function library <jody@jodybruchon.com>
* Copyright (C) 2015-2017
* Distributed under the GNU General Public License version 2
*/
#ifndef JODY_STRING_H
#define JODY_STRING_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <unistd.h>
extern int strncaseeq(const char *s1, const char *s2, size_t len);
extern int strcaseeq(const char *s1, const char *s2);
extern int strneq(const char *s1, const char *s2, size_t len);
extern int streq(const char *s1, const char *s2);
/* Inline strcpy() */
inline void xstrcpy(char * restrict dest, const char * restrict src)
{
while (*src != '\0') {
*dest = *src;
dest++; src++;
}
*dest = '\0';
}
#ifdef __cplusplus
}
#endif
#endif /* JODY_STRING_H */
.\" Copyright (c) 2014-2017 Jody Bruchon
.\" Licensed under the GNU General Public License v2
.\"
.TH winregfs 8 "10 Mar 2017" "mount.winregfs"
.SH NAME
winregfs \- Windows registry FUSE filesystem
.SH SYNOPSIS
.B mount.winregfs
\fB[\fIfuse_options\fP\fB[,...]]\fR
.I hivefile mountpoint
.SH DESCRIPTION
\fBwinregfs\fR is a FUSE-based filesystem driver that enables accessing of
Windows registry hive files as ordinary filesystems. Registry hive file
editing can be performed with ordinary shell scripts and command-line tools
once mounted.
Registry values are shown as files with a file extension corresponding to
the data type of the value. These are generally named after the REG_* types
seen in the Windows registry editor. For example, \fBdw\fP is a DWORD,
\fBsz\fP is a string, \fBesz\fP is an expanding string, \fBbin\fP is a raw
binary value, and \fBmsz\fP is a multi-line string. Types different from
the "standard" types may appear in rare instances.
Because registry keys and values can have forward slashes in their names,
there is a special word \fB_SLASH_\fP that is used in place of any real
slashes and is converted back-and-forth automatically.
Opening a value's name without the extension is supported, but you should
always use the extension if possible to avoid ambiguity issues.
.SH KNOWN ISSUES
\fBwinregfs\fP does not currently support writing value data greater than
8,192 bytes (8 KiB) in size. If such a write occurs, the data will be
truncated and an error will be returned. Unicode data is not currently
supported, partly due to a lack of support in the ntreg library.
Incorrect or unrecognized structures in a registry file may cause this
program to crash. It is not recommended for use on important data and
while most operations generally work as expected, you use it at your own
risk. Please report any bugs you encounter.
\fBwinregfs\fP loads the entire hive file into one large chunk of memory.
This is a side effect of adopting the low-level registry library from the
program \fBchntpw\fP. There is a silent delay as the hive is loaded and
if the file is large enough there is a chance of failure due to being
unable to allocate enough contiguous memory. Changing this behavior is a
very difficult task due to how the ntreg library works with the data.
.SH SEE ALSO
.BR fusermount (8),
.BR fsck.winregfs (8)
This diff is collapsed.
This diff is collapsed.
/*
* Windows Registry FUSE Filesystem
*
* Version number definitions
*
*/
#ifndef WINREGFS_VERSION_H
#define WINREGFS_VERSION_H
#define VER "0.7"
#define VERDATE "2017-03-10"
#endif /* WINREGFS_VERSION_H */
This diff is collapsed.
/*
* Windows Registry FUSE Filesystem
*
* Copyright (C) 2014-2017 by Jody Bruchon <jody@jodybruchon.com>
*
* Licensed under GNU GPL v2. See LICENSE and README for details.
*
*/
#ifndef WINREGFS_H
#define WINREGFS_H
#include "version.h"
#ifndef FSCK_WINREGFS
#define FUSE_USE_VERSION 26
#include <fuse.h>
#endif
#include "jody_hash.h"
#include "config.h"
/*** Check config.h settings for sanity ***/
#if ENABLE_NKOFS_CACHE_STATS
# if !ENABLE_NKOFS_CACHE
# warning ENABLE_NKOFS_CACHE_STATS requires ENABLE_NKOFS_CACHE
# undef ENABLE_NKOFS_CACHE
# define ENABLE_NKOFS_CACHE 1
# endif
#endif
#if ENABLE_DEBUG_LOGGING
# if !ENABLE_LOGGING
# warning ENABLE_DEBUG_LOGGING requires ENABLE_LOGGING
# undef ENABLE_LOGGING
# define ENABLE_LOGGING 1
# endif
#endif
#if ENABLE_NKOFS_CACHE
# if !NKOFS_CACHE_ITEMS
# error ENABLE_NKOFS_CACHE enabled; NKOFS_CACHE_ITEMS must be set and non-zero
# endif
#endif
#ifdef FSCK_WINREGFS
#undef ENABLE_LOGGING
#define ENABLE_LOGGING 0
#undef ENABLE_THREADED
#define ENABLE_THREADED 0
#endif
/*** End sanity checks ***/
#if ENABLE_NKOFS_CACHE_STATS
#define CACHE_HIT 0
#define CACHE_MISS 1
#define HASH_HIT 2
#define HASH_MISS 3
#define HASH_FAIL 4
#else
#define nk_cache_stats(a,b)
#endif /* NKOFS_CACHE_STATS */
/* Data structures */
struct winregfs_data {
struct hive *hive;
int ro;
#if ENABLE_LOGGING
FILE *log;
#endif
#if ENABLE_NKOFS_CACHE
/* Cache previous nkofs/path/key sets up to NKOFS_CACHE_ITEMS */
int nk_cache_pos;
char *nk_last_path[NKOFS_CACHE_ITEMS];
int nk_last_nkofs[NKOFS_CACHE_ITEMS];
struct nk_key *nk_last_key[NKOFS_CACHE_ITEMS];
hash_t nk_hash[NKOFS_CACHE_ITEMS];
# if ENABLE_NKOFS_CACHE_STATS
int delay; /* Cache log throttling interval */
int nk_cache_miss;
int nk_cache_hit;
int nk_hash_miss;
int nk_hash_hit;
int nk_hash_fail;
# endif
# if ENABLE_THREADED
pthread_mutex_t *lock;
# endif
#endif
};
/* Shortcut to pull winregfs_data structure into a function
This MUST BE PLACED between variable declarations and code in ANY
function that uses winregfs logging or data */
#define LOAD_WD() struct winregfs_data *wd; \
wd = fuse_get_context()->private_data;
/* Enable/disable logging
We check wd for non-NULL before logging since wd may be unallocated
during startup before fuse_main() */
#if ENABLE_LOGGING
# define LOG_IS_USED 1
# define LOG(...) if (wd) { \
fprintf(wd->log, __VA_ARGS__); fflush(wd->log); \
} else printf(__VA_ARGS__);
# define LOAD_WD_LOGONLY() struct winregfs_data *wd; \
wd = fuse_get_context()->private_data;
#else
# define LOAD_WD_LOGONLY()
# if ENABLE_DEBUG_PRINTF
# define LOG_IS_USED 1
# define LOG(...) printf(__VA_ARGS__)
# else
# define LOG(...)
# endif
#endif
/* Use DLOG for places where logging may be high-volume */
#if ENABLE_DEBUG_LOGGING
# define LOG_IS_USED 1
# define DLOG(...) if (wd) { \
fprintf(wd->log, __VA_ARGS__); fflush(wd->log); \
} else printf(__VA_ARGS__);
#else
# if ENABLE_DEBUG_PRINTF
# define LOG_IS_USED 1
# define DLOG(...) printf(__VA_ARGS__);
# else
# define DLOG(...)
# endif
#endif
#ifndef LOG_IS_USED
#define LOG_IS_USED 0
#endif
/* Threaded mode mutex */
#if ENABLE_THREADED
#define LOCK() pthread_mutex_lock(wd->lock)
#define UNLOCK() pthread_mutex_unlock(wd->lock)
#else
#define LOCK()
#define UNLOCK()
#endif
void invalidate_nk_cache(void);
#endif /* WINREGFS_H */