summaryrefslogtreecommitdiffstats
path: root/src/pmdk/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmdk/utils')
-rw-r--r--src/pmdk/utils/.gitignore1
-rw-r--r--src/pmdk/utils/CHECK_WHITESPACE.PS120
-rw-r--r--src/pmdk/utils/CREATE-ZIP.PS183
-rw-r--r--src/pmdk/utils/CSTYLE.ps137
-rw-r--r--src/pmdk/utils/Makefile12
-rw-r--r--src/pmdk/utils/README5
-rw-r--r--src/pmdk/utils/SRCVERSION.ps1158
-rwxr-xr-xsrc/pmdk/utils/build-dpkg.sh836
-rwxr-xr-xsrc/pmdk/utils/build-rpm.sh263
-rwxr-xr-xsrc/pmdk/utils/check-area.sh74
-rwxr-xr-xsrc/pmdk/utils/check-commit.sh50
-rwxr-xr-xsrc/pmdk/utils/check-commits.sh43
-rwxr-xr-xsrc/pmdk/utils/check-manpage62
-rwxr-xr-xsrc/pmdk/utils/check-manpages16
-rwxr-xr-xsrc/pmdk/utils/check-os.sh30
-rwxr-xr-xsrc/pmdk/utils/check-shebang.sh30
-rw-r--r--src/pmdk/utils/check_license/.gitignore1
-rwxr-xr-xsrc/pmdk/utils/check_license/check-headers.sh192
-rwxr-xr-xsrc/pmdk/utils/check_license/check-ms-license.pl62
-rwxr-xr-xsrc/pmdk/utils/check_license/file-exceptions.sh7
-rwxr-xr-xsrc/pmdk/utils/check_sdk_version.py76
-rwxr-xr-xsrc/pmdk/utils/check_whitespace210
-rwxr-xr-xsrc/pmdk/utils/copy-source.sh36
-rwxr-xr-xsrc/pmdk/utils/cstyle1037
-rw-r--r--src/pmdk/utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch27
-rw-r--r--src/pmdk/utils/docker/README19
-rwxr-xr-xsrc/pmdk/utils/docker/build-CI.sh143
-rwxr-xr-xsrc/pmdk/utils/docker/build-local.sh111
-rwxr-xr-xsrc/pmdk/utils/docker/configure-tests.sh105
-rw-r--r--src/pmdk/utils/docker/images/0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch37
-rw-r--r--src/pmdk/utils/docker/images/Dockerfile.fedora-31120
-rw-r--r--src/pmdk/utils/docker/images/Dockerfile.ubuntu-19.10121
-rw-r--r--src/pmdk/utils/docker/images/README6
-rwxr-xr-xsrc/pmdk/utils/docker/images/build-image.sh53
-rwxr-xr-xsrc/pmdk/utils/docker/images/download-scripts.sh32
-rwxr-xr-xsrc/pmdk/utils/docker/images/install-libfabric.sh40
-rwxr-xr-xsrc/pmdk/utils/docker/images/install-libndctl.sh60
-rwxr-xr-xsrc/pmdk/utils/docker/images/install-valgrind.sh52
-rwxr-xr-xsrc/pmdk/utils/docker/images/push-image.sh51
-rw-r--r--src/pmdk/utils/docker/ppc64le.blacklist19
-rwxr-xr-xsrc/pmdk/utils/docker/prepare-for-build.sh25
-rwxr-xr-xsrc/pmdk/utils/docker/pull-or-rebuild-image.sh112
-rwxr-xr-xsrc/pmdk/utils/docker/run-build-package.sh47
-rwxr-xr-xsrc/pmdk/utils/docker/run-build.sh34
-rwxr-xr-xsrc/pmdk/utils/docker/run-coverage.sh52
-rwxr-xr-xsrc/pmdk/utils/docker/run-coverity.sh71
-rwxr-xr-xsrc/pmdk/utils/docker/run-doc-update.sh76
-rwxr-xr-xsrc/pmdk/utils/docker/set-ci-vars.sh96
-rwxr-xr-xsrc/pmdk/utils/docker/set-vars.sh12
-rw-r--r--src/pmdk/utils/docker/test_package/.gitignore1
-rw-r--r--src/pmdk/utils/docker/test_package/Makefile21
-rw-r--r--src/pmdk/utils/docker/test_package/README6
-rw-r--r--src/pmdk/utils/docker/test_package/test_package.c41
-rwxr-xr-xsrc/pmdk/utils/docker/valid-branches.sh12
-rwxr-xr-xsrc/pmdk/utils/get_aliases.sh110
-rwxr-xr-xsrc/pmdk/utils/git-years8
-rw-r--r--src/pmdk/utils/libpmem.pc.in9
-rw-r--r--src/pmdk/utils/libpmem2.pc.in9
-rw-r--r--src/pmdk/utils/libpmemblk.pc.in9
-rw-r--r--src/pmdk/utils/libpmemlog.pc.in9
-rw-r--r--src/pmdk/utils/libpmemobj.pc.in10
-rw-r--r--src/pmdk/utils/libpmempool.pc.in10
-rw-r--r--src/pmdk/utils/librpmem.pc.in9
-rw-r--r--src/pmdk/utils/magic-install.sh15
-rw-r--r--src/pmdk/utils/magic-uninstall.sh21
-rwxr-xr-xsrc/pmdk/utils/md2man.sh67
-rw-r--r--src/pmdk/utils/os-banned63
-rw-r--r--src/pmdk/utils/pkg-common.sh56
-rw-r--r--src/pmdk/utils/pkg-config.sh17
-rw-r--r--src/pmdk/utils/pmdk.magic15
-rw-r--r--src/pmdk/utils/pmdk.spec.in710
-rw-r--r--src/pmdk/utils/ps_analyze.ps131
-rwxr-xr-xsrc/pmdk/utils/sort_solution128
-rwxr-xr-xsrc/pmdk/utils/style_check.sh137
-rwxr-xr-xsrc/pmdk/utils/version.sh62
75 files changed, 6448 insertions, 0 deletions
diff --git a/src/pmdk/utils/.gitignore b/src/pmdk/utils/.gitignore
new file mode 100644
index 000000000..c4c4ffc6a
--- /dev/null
+++ b/src/pmdk/utils/.gitignore
@@ -0,0 +1 @@
+*.zip
diff --git a/src/pmdk/utils/CHECK_WHITESPACE.PS1 b/src/pmdk/utils/CHECK_WHITESPACE.PS1
new file mode 100644
index 000000000..5ffeedc4a
--- /dev/null
+++ b/src/pmdk/utils/CHECK_WHITESPACE.PS1
@@ -0,0 +1,20 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2017, Intel Corporation
+#
+# CHECK_WHITESPACE.PS1 -- script to check coding style
+#
+# XXX - integrate with VS projects and execute for each build
+#
+
+$scriptdir = Split-Path -Parent $PSCommandPath
+$rootdir = $scriptdir + "\.."
+$whitepace = $rootdir + "\utils\check_whitespace"
+
+If ( Get-Command -Name perl -ErrorAction SilentlyContinue ) {
+ &perl $whitepace -g
+ if ($LASTEXITCODE -ne 0) {
+ Exit $LASTEXITCODE
+ }
+} else {
+ Write-Output "Cannot execute check_whitespace - perl is missing"
+}
diff --git a/src/pmdk/utils/CREATE-ZIP.PS1 b/src/pmdk/utils/CREATE-ZIP.PS1
new file mode 100644
index 000000000..902cb07a9
--- /dev/null
+++ b/src/pmdk/utils/CREATE-ZIP.PS1
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2019, Intel Corporation
+#
+# CREATE-ZIP.PS1 -- script to create release zip package
+#
+
+#
+# parameter handling
+#
+[CmdletBinding(PositionalBinding=$false)]
+Param(
+ [alias("b")]
+ $build = "debug",
+ [alias("v")]
+ $version = "0",
+ [alias("e")]
+ $extended = "0"
+ )
+
+$scriptdir = Split-Path -Parent $PSCommandPath
+$rootdir = $scriptdir + "\..\"
+
+$builddir = $rootdir + "\src\x64\"
+$zipdir = $builddir + "\pmdk\"
+
+if ($version -eq "0") {
+ $git = Get-Command -Name git -ErrorAction SilentlyContinue
+ if ($git) {
+ $version = $(git describe)
+ } else {
+ $version = "0"
+ }
+}
+
+$zipfile = $builddir + "\pmdk-" + $version + "-win-x64-" + $build + ".zip"
+
+Remove-Item $zipdir -Force -Recurse -ea si
+Get-ChildItem | Where-Object {$_.Name -Match "pmdk-.*-win-x64.zip"} | Remove-Item -Force -ea si
+New-Item -ItemType directory -Path ( $zipdir) -Force | Out-Null
+New-Item -ItemType directory -Path ( $zipdir + "\bin\") -Force | Out-Null
+New-Item -ItemType directory -Path ( $zipdir + "\lib\") -Force | Out-Null
+
+$libs = @("libpmem", "libpmemblk", "libpmemlog", "libpmemobj", "libpmempool")
+$apps = @("pmempool")
+$apps_extended = @("pmempool", "pmemalloc", "pmemdetect", "pmemspoil", "pmemwrite")
+
+if ($extended -eq "1") {
+ $apps = $apps_extended
+}
+
+foreach ($lib in $libs) {
+ Copy-Item ($builddir + $build + "\libs\" + $lib + ".dll") ($zipdir + "\bin\")
+ foreach ($ex in @(".lib", ".pdb")) {
+ Copy-Item ($builddir + $build + "\libs\" + $lib + $ex) ($zipdir + "\lib\")
+ }
+}
+foreach ($app in $apps) {
+ if ($app -eq "pmempool") {
+ Copy-Item ($builddir + $build + "\libs\" + $app + ".exe") ($zipdir + "\bin\")
+ Copy-Item ($builddir + $build + "\libs\" + $app + ".pdb") ($zipdir + "\lib\")
+ } else {
+ Copy-Item ($builddir + $build + "\tests\" + $app + ".exe") ($zipdir + "\bin\")
+ Copy-Item ($builddir + $build + "\tests\" + $app + ".pdb") ($zipdir + "\lib\")
+ }
+}
+
+Copy-Item -Recurse ($rootdir + "src\include") ($zipdir)
+Remove-Item -Force ($zipdir + "include\.cstyleignore")
+Remove-Item -Force ($zipdir + "include\README")
+Remove-Item -Force ($zipdir + "include\librpmem.h")
+Copy-Item ($rootdir + "README.md") ($zipdir)
+Copy-Item ($rootdir + "LICENSE") ($zipdir)
+Copy-Item ($rootdir + "ChangeLog") ($zipdir)
+
+Add-Type -Assembly System.IO.Compression.FileSystem
+$comprlevel = [System.IO.Compression.CompressionLevel]::Optimal
+
+if (Test-Path ($zipdir)) {
+ [System.IO.Compression.ZipFile]::CreateFromDirectory($zipdir, $zipfile,
+ $comprlevel, $true)
+}
+
+Remove-Item $zipdir -Force -Recurse -ea si
diff --git a/src/pmdk/utils/CSTYLE.ps1 b/src/pmdk/utils/CSTYLE.ps1
new file mode 100644
index 000000000..42b22b34c
--- /dev/null
+++ b/src/pmdk/utils/CSTYLE.ps1
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2017, Intel Corporation
+#
+# CSTYLE.ps1 -- script to check coding style
+#
+# XXX - integrate with VS projects and execute for each build
+#
+
+$scriptdir = Split-Path -Parent $PSCommandPath
+$rootdir = $scriptdir + "\.."
+$cstyle = $rootdir + "\utils\cstyle"
+$checkdir = $rootdir
+
+# XXX - *.cpp/*.hpp files not supported yet
+$include = @( "*.c", "*.h" )
+
+If ( Get-Command -Name perl -ErrorAction SilentlyContinue ) {
+ Get-ChildItem -Path $checkdir -Recurse -Include $include | `
+ Where-Object { $_.FullName -notlike "*jemalloc*" } | `
+ ForEach-Object {
+ $IGNORE = $_.DirectoryName + "\.cstyleignore"
+ if(Test-Path $IGNORE) {
+ if((Select-String $_.Name $IGNORE)) {
+ return
+ }
+ }
+ $_
+ } | ForEach-Object {
+ Write-Output $_.FullName
+ & perl $cstyle $_.FullName
+ if ($LASTEXITCODE -ne 0) {
+ Exit $LASTEXITCODE
+ }
+ }
+} else {
+ Write-Output "Cannot execute cstyle - perl is missing"
+}
diff --git a/src/pmdk/utils/Makefile b/src/pmdk/utils/Makefile
new file mode 100644
index 000000000..14352886f
--- /dev/null
+++ b/src/pmdk/utils/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)\
+ $(filter $(subst *,%,$2),$d)))
+
+SCRIPTS = $(call rwildcard,,*.sh)
+
+cstyle:
+ ./check-shebang.sh $(SCRIPTS)
+
+.PHONY: cstyle
diff --git a/src/pmdk/utils/README b/src/pmdk/utils/README
new file mode 100644
index 000000000..07a762ca2
--- /dev/null
+++ b/src/pmdk/utils/README
@@ -0,0 +1,5 @@
+Persistent Memory Development Kit
+
+This is utils/README.
+
+The scripts found here are used during library development.
diff --git a/src/pmdk/utils/SRCVERSION.ps1 b/src/pmdk/utils/SRCVERSION.ps1
new file mode 100644
index 000000000..8e6e43639
--- /dev/null
+++ b/src/pmdk/utils/SRCVERSION.ps1
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# SRCVERSION.PS1 -- script to create SCRVERSION macro and generate srcversion.h
+#
+
+#
+# Windows dll versioning supports only fixed number of fields. The most
+# important are MAJOR, MINOR and REVISION. We have 3-compoment releases
+# (e.g. 1.5.1) with release candidates, so we have to encode this information
+# into this fixed number of fields. That's why we abuse REVISION to encode both
+# 3rd component and rc status.
+# REVISION = 3RDCOMP * 1000 + (!is_rc) * 100 + rc.
+#
+# Examples:
+# +---------------------+-----+-----+--------+-----+------+-------+----------+
+# |git describe --long |MAJOR|MINOR|REVISION|BUILD|BUGFIX|PRIVATE|PRERELEASE|
+# +---------------------+-----+-----+--------+-----+------+-------+----------+
+# |1.5-rc2-0-12345678 | 1| 5| 2| 0| false| false| true|
+# |1.5-rc3-6-12345678 | 1| 5| 3| 6| false| true| true|
+# |1.5-0-12345678 | 1| 5| 100| 0| false| false| false|
+# |1.5-6-123345678 | 1| 5| 100| 6| false| true| false|
+# |1.5.2-rc1-0-12345678 | 1| 5| 2001| 0| true| false| true|
+# |1.5.2-rc4-6-12345678 | 1| 5| 2004| 6| true| true| true|
+# |1.5.2-0-12345678 | 1| 5| 2100| 0| true| false| false|
+# |1.5.2-6-12345678 | 1| 5| 2100| 6| true| true| false|
+# +---------------------+-----+-----+--------+-----+------+-------+----------+
+#
+
+$scriptPath = Split-Path -parent $MyInvocation.MyCommand.Definition
+$file_path = $scriptPath + "\..\src\windows\include\srcversion.h"
+$git_version_file = $scriptPath + "\..\GIT_VERSION"
+$version_file = $scriptPath + "\..\VERSION"
+$git = Get-Command -Name git -ErrorAction SilentlyContinue
+
+if (Test-Path $file_path) {
+ $old_src_version = Get-Content $file_path | `
+ Where-Object { $_ -like '#define SRCVERSION*' }
+} else {
+ $old_src_version = ""
+}
+
+$git_version = ""
+$git_version_hash = ""
+
+if (Test-Path $git_version_file) {
+ $git_version = Get-Content $git_version_file
+ if ($git_version -eq "`$Format:%h`$") {
+ $git_version = ""
+ } else {
+ $git_version_hash = $git_version
+ }
+}
+
+$PRERELEASE = $false
+$BUGFIX = $false
+$PRIVATE = $true
+$CUSTOM = $false
+
+if ($null -ne $args[0]) {
+ $version = $args[0]
+ $ver_array = $version.split("-+")
+} elseif (Test-Path $version_file) {
+ $version = Get-Content $version_file
+ $ver_array = $version.split("-+")
+} elseif ($git_version_hash -ne "") {
+ $MAJOR = 0
+ $MINOR = 0
+ $REVISION = 0
+ $BUILD = 0
+
+ $version = $git_version_hash
+ $CUSTOM = $true
+ $version_custom_msg = "#define VERSION_CUSTOM_MSG `"$git_version_hash`""
+} elseif ($null -ne $git) {
+ $version = $(git describe)
+ $ver_array = $(git describe --long).split("-+")
+} else {
+ $MAJOR = 0
+ $MINOR = 0
+ $REVISION = 0
+ $BUILD = 0
+
+ $version = "UNKNOWN_VERSION"
+ $CUSTOM = $true
+ $version_custom_msg = "#define VERSION_CUSTOM_MSG `"UNKNOWN_VERSION`""
+}
+
+if ($null -ne $ver_array) {
+ $ver_dots = $ver_array[0].split(".")
+ $MAJOR = $ver_dots[0]
+ $MINOR = $ver_dots[1]
+ if ($ver_dots.length -ge 3) {
+ $REV = $ver_dots[2]
+ $BUGFIX = $true
+ } else {
+ $REV = 0
+ }
+
+ $REVISION = 1000 * $REV
+ $BUILD = $ver_array[$ver_array.length - 2]
+
+ if ($ver_array.length -eq 4) {
+ # <MAJOR>.<MINOR>[.<BUGFIX>]-<SUFFIX><REVISION>-<BUILD>-<HASH>
+
+ if ($ver_array[1].StartsWith("rc")) {
+ # <MAJOR>.<MINOR>[.<BUGFIX>]-rc<REVISION>-<BUILD>-<HASH>
+ $REVISION += $ver_array[1].Substring("rc".Length)
+ $PRERELEASE = $true
+ $version = "$($ver_array[0])-$($ver_array[1])+git$($ver_array[2]).$($ver_array[3])"
+ } else {
+ # <MAJOR>.<MINOR>[.<BUGFIX>]-<SOMETHING>-<BUILD>-<HASH>
+ throw "Unknown version format"
+ }
+ } else {
+ # <MAJOR>.<MINOR>[.<BUGFIX>]-<BUILD>-<HASH>
+ $REVISION += 100
+ $version = "$($ver_array[0])+git$($ver_array[1]).$($ver_array[2])"
+ }
+
+ if ($BUILD -eq 0) {
+ # it is not a (pre)release build
+ $PRIVATE = $false
+ }
+}
+
+$src_version = "#define SRCVERSION `"$version`""
+
+if ($old_src_version -eq $src_version) {
+ exit 0
+}
+
+Write-Output "updating source version: $version"
+Write-Output $src_version > $file_path
+
+Write-Output "#ifdef RC_INVOKED" >> $file_path
+
+Write-Output "#define MAJOR $MAJOR" >> $file_path
+Write-Output "#define MINOR $MINOR" >> $file_path
+Write-Output "#define REVISION $REVISION" >> $file_path
+Write-Output "#define BUILD $BUILD" >> $file_path
+
+if ($PRERELEASE) {
+ Write-Output "#define PRERELEASE 1" >> $file_path
+}
+if ($BUGFIX) {
+ Write-Output "#define BUGFIX 1" >> $file_path
+}
+if ($PRIVATE) {
+ Write-Output "#define PRIVATE 1" >> $file_path
+}
+if ($CUSTOM) {
+ Write-Output "#define CUSTOM 1" >> $file_path
+ Write-Output $version_custom_msg >> $file_path
+}
+
+Write-Output "#endif" >> $file_path
diff --git a/src/pmdk/utils/build-dpkg.sh b/src/pmdk/utils/build-dpkg.sh
new file mode 100755
index 000000000..cb96f4185
--- /dev/null
+++ b/src/pmdk/utils/build-dpkg.sh
@@ -0,0 +1,836 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2020, Intel Corporation
+
+#
+# build-dpkg.sh - Script for building deb packages
+#
+
+set -e
+
+SCRIPT_DIR=$(dirname $0)
+source $SCRIPT_DIR/pkg-common.sh
+
+#
+# usage -- print usage message and exit
+#
+usage()
+{
+ [ "$1" ] && echo Error: $1
+ cat >&2 <<EOF
+Usage: $0 [ -h ] -t version-tag -s source-dir -w working-dir -o output-dir
+ [ -e build-experimental ] [ -c run-check ]
+ [ -n with-ndctl ] [ -f testconfig-file ]
+
+-h print this help message
+-t version-tag source version tag
+-s source-dir source directory
+-w working-dir working directory
+-o output-dir output directory
+-e build-experimental build experimental packages
+-c run-check run package check
+-n with-ndctl build with libndctl
+-f testconfig-file custom testconfig.sh
+EOF
+ exit 1
+}
+
+#
+# command-line argument processing...
+#
+args=`getopt he:c:r:n:t:d:s:w:o:f: $*`
+[ $? != 0 ] && usage
+set -- $args
+for arg
+do
+ receivetype=auto
+ case "$arg"
+ in
+ -e)
+ EXPERIMENTAL="$2"
+ shift 2
+ ;;
+ -c)
+ BUILD_PACKAGE_CHECK="$2"
+ shift 2
+ ;;
+ -f)
+ TEST_CONFIG_FILE="$2"
+ shift 2
+ ;;
+ -r)
+ BUILD_RPMEM="$2"
+ shift 2
+ ;;
+ -n)
+ NDCTL_ENABLE="$2"
+ shift 2
+ ;;
+ -t)
+ PACKAGE_VERSION_TAG="$2"
+ shift 2
+ ;;
+ -s)
+ SOURCE="$2"
+ shift 2
+ ;;
+ -w)
+ WORKING_DIR="$2"
+ shift 2
+ ;;
+ -o)
+ OUT_DIR="$2"
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+# check for mandatory arguments
+if [ -z "$PACKAGE_VERSION_TAG" -o -z "$SOURCE" -o -z "$WORKING_DIR" -o -z "$OUT_DIR" ]
+then
+ error "Mandatory arguments missing"
+ usage
+fi
+
+PMEM2_INSTALL="y"
+
+PREFIX=usr
+LIB_DIR=$PREFIX/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)
+INC_DIR=$PREFIX/include
+MAN1_DIR=$PREFIX/share/man/man1
+MAN3_DIR=$PREFIX/share/man/man3
+MAN5_DIR=$PREFIX/share/man/man5
+MAN7_DIR=$PREFIX/share/man/man7
+
+DOC_DIR=$PREFIX/share/doc
+if [ "$EXTRA_CFLAGS_RELEASE" = "" ]; then
+ export EXTRA_CFLAGS_RELEASE="-ggdb -fno-omit-frame-pointer"
+fi
+
+LIBFABRIC_MIN_VERSION=1.4.2
+NDCTL_MIN_VERSION=60.1
+
+function convert_changelog() {
+ while read line
+ do
+ if [[ $line =~ $REGEX_DATE_AUTHOR ]]
+ then
+ DATE="${BASH_REMATCH[1]}"
+ AUTHOR="${BASH_REMATCH[2]}"
+ echo " * ${DATE} ${AUTHOR}"
+ elif [[ $line =~ $REGEX_MESSAGE_START ]]
+ then
+ MESSAGE="${BASH_REMATCH[1]}"
+ echo " - ${MESSAGE}"
+ elif [[ $line =~ $REGEX_MESSAGE ]]
+ then
+ MESSAGE="${BASH_REMATCH[1]}"
+ echo " ${MESSAGE}"
+ fi
+ done < $1
+}
+
+function rpmem_install_triggers_overrides() {
+cat << EOF > debian/librpmem.install
+$LIB_DIR/librpmem.so.*
+EOF
+
+cat << EOF > debian/librpmem.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+librpmem: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/librpmem-dev.install
+$LIB_DIR/pmdk_debug/librpmem.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/librpmem.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/librpmem.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/librpmem.so
+$LIB_DIR/pkgconfig/librpmem.pc
+$INC_DIR/librpmem.h
+$MAN7_DIR/librpmem.7
+$MAN3_DIR/rpmem_*.3
+EOF
+
+cat << EOF > debian/librpmem-dev.triggers
+interest man-db
+EOF
+
+cat << EOF > debian/librpmem-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+EOF
+
+cat << EOF > debian/rpmemd.install
+usr/bin/rpmemd
+$MAN1_DIR/rpmemd.1
+EOF
+
+cat << EOF > debian/rpmemd.triggers
+interest man-db
+EOF
+
+cat << EOF > debian/rpmemd.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+EOF
+}
+
+function append_rpmem_control() {
+cat << EOF >> $CONTROL_FILE
+
+Package: librpmem
+Architecture: any
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory remote access support library
+ librpmem provides low-level support for remote access to persistent memory
+ (pmem) utilizing RDMA-capable RNICs. The library can be used to replicate
+ remotely a memory region over RDMA protocol. It utilizes appropriate
+ persistency mechanism based on remote node’s platform capabilities. The
+ librpmem utilizes the ssh client to authenticate a user on remote node and for
+ encryption of connection’s out-of-band configuration data.
+ .
+ This library is for applications that use remote persistent memory directly,
+ without the help of any library-supplied transactions or memory allocation.
+ Higher-level libraries that build on libpmem are available and are recommended
+ for most applications.
+
+Package: librpmem-dev
+Section: libdevel
+Architecture: any
+Depends: librpmem (=\${binary:Version}), libpmem-dev, \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for librpmem
+ librpmem provides low-level support for remote access to persistent memory
+ (pmem) utilizing RDMA-capable RNICs.
+ .
+ This package contains libraries and header files used for linking programs
+ against librpmem.
+
+Package: rpmemd
+Section: misc
+Architecture: any
+Priority: optional
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: rpmem daemon
+ Daemon for Remote Persistent Memory support.
+EOF
+}
+
+function libpmem2_install_triggers_overrides() {
+cat << EOF > debian/libpmem2.install
+$LIB_DIR/libpmem2.so.*
+EOF
+
+cat << EOF > debian/libpmem2.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmem2: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmem2-dev.install
+$LIB_DIR/pmdk_debug/libpmem2.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmem2.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmem2.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmem2.so
+$LIB_DIR/pkgconfig/libpmem2.pc
+$INC_DIR/libpmem2.h
+$MAN7_DIR/libpmem2.7
+$MAN3_DIR/pmem2_*.3
+EOF
+
+cat << EOF > debian/libpmem2-dev.triggers
+interest man-db
+EOF
+
+cat << EOF > debian/libpmem2-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+EOF
+}
+
+function append_libpmem2_control() {
+cat << EOF >> $CONTROL_FILE
+
+Package: libpmem2
+Architecture: any
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory low level support library
+ libpmem2 provides low level persistent memory support. In particular, support
+ for the persistent memory instructions for flushing changes to pmem is
+ provided.
+
+Package: libpmem2-dev
+Section: libdevel
+Architecture: any
+Depends: libpmem2 (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmem2
+ libpmem2 provides low level persistent memory support. In particular, support
+ for the persistent memory instructions for flushing changes to pmem is
+ provided.
+EOF
+}
+
+function daxio_install_triggers_overrides() {
+cat << EOF > debian/daxio.install
+usr/bin/daxio
+$MAN1_DIR/daxio.1
+EOF
+
+cat << EOF > debian/daxio.triggers
+interest man-db
+EOF
+
+cat << EOF > debian/daxio.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+EOF
+}
+
+function append_daxio_control() {
+cat << EOF >> $CONTROL_FILE
+
+Package: daxio
+Section: misc
+Architecture: any
+Priority: optional
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: dd-like tool to read/write to a devdax device
+ The daxio utility performs I/O on Device DAX devices or zeroes a Device
+ DAX device. Since the standard I/O APIs (read/write) cannot be used
+ with Device DAX, data transfer is performed on a memory-mapped device.
+ The daxio may be used to dump Device DAX data to a file, restore data from
+ a backup copy, move/copy data to another device or to erase data from
+ a device.
+EOF
+}
+
+if [ "${BUILD_PACKAGE_CHECK}" == "y" ]
+then
+CHECK_CMD="
+override_dh_auto_test:
+ dh_auto_test
+ if [ -f $TEST_CONFIG_FILE ]; then\
+ cp $TEST_CONFIG_FILE src/test/testconfig.sh;\
+ else\
+ echo 'PMEM_FS_DIR=/tmp' > src/test/testconfig.sh; \
+ echo 'PMEM_FS_DIR_FORCE_PMEM=1' >> src/test/testconfig.sh; \
+ echo 'TEST_BUILD=\"debug nondebug\"' >> src/test/testconfig.sh; \
+ echo 'TEST_FS=\"pmem any none\"' >> src/test/testconfig.sh; \
+ fi
+ make pcheck ${PCHECK_OPTS}
+"
+else
+CHECK_CMD="
+override_dh_auto_test:
+
+"
+fi
+
+check_tool debuild
+check_tool dch
+check_file $SCRIPT_DIR/pkg-config.sh
+
+source $SCRIPT_DIR/pkg-config.sh
+
+PACKAGE_VERSION=$(get_version $PACKAGE_VERSION_TAG)
+PACKAGE_RELEASE=1
+PACKAGE_SOURCE=${PACKAGE_NAME}-${PACKAGE_VERSION}
+PACKAGE_TARBALL_ORIG=${PACKAGE_NAME}_${PACKAGE_VERSION}.orig.tar.gz
+MAGIC_INSTALL=utils/magic-install.sh
+MAGIC_UNINSTALL=utils/magic-uninstall.sh
+CONTROL_FILE=debian/control
+
+[ -d $WORKING_DIR ] || mkdir $WORKING_DIR
+[ -d $OUT_DIR ] || mkdir $OUT_DIR
+
+OLD_DIR=$PWD
+
+cd $WORKING_DIR
+
+check_dir $SOURCE
+
+mv $SOURCE $PACKAGE_SOURCE
+tar zcf $PACKAGE_TARBALL_ORIG $PACKAGE_SOURCE
+
+cd $PACKAGE_SOURCE
+
+rm -rf debian
+mkdir debian
+
+# Generate compat file
+cat << EOF > debian/compat
+9
+EOF
+
+# Generate control file
+cat << EOF > $CONTROL_FILE
+Source: $PACKAGE_NAME
+Maintainer: $PACKAGE_MAINTAINER
+Section: libs
+Priority: optional
+Standards-version: 4.1.4
+Build-Depends: debhelper (>= 9)
+Homepage: https://pmem.io/pmdk/
+
+Package: libpmem
+Architecture: any
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory low level support library
+ libpmem provides low level persistent memory support. In particular, support
+ for the persistent memory instructions for flushing changes to pmem is
+ provided.
+
+Package: libpmem-dev
+Section: libdevel
+Architecture: any
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmem
+ libpmem provides low level persistent memory support. In particular, support
+ for the persistent memory instructions for flushing changes to pmem is
+ provided.
+
+Package: libpmemblk
+Architecture: any
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory block array support library
+ libpmemblk implements a pmem-resident array of blocks, all the same size, where
+ a block is updated atomically with respect to power failure or program
+ interruption (no torn blocks).
+
+Package: libpmemblk-dev
+Section: libdevel
+Architecture: any
+Depends: libpmemblk (=\${binary:Version}), libpmem-dev, \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmemblk
+ libpmemblk implements a pmem-resident array of blocks, all the same size, where
+ a block is updated atomically with respect to power failure or program
+ interruption (no torn blocks).
+
+Package: libpmemlog
+Architecture: any
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory log file support library
+ libpmemlog implements a pmem-resident log file.
+
+Package: libpmemlog-dev
+Section: libdevel
+Architecture: any
+Depends: libpmemlog (=\${binary:Version}), libpmem-dev, \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmemlog
+ libpmemlog implements a pmem-resident log file.
+
+Package: libpmemobj
+Architecture: any
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory object store support library
+ libpmemobj turns a persistent memory file into a flexible object store,
+ supporting transactions, memory management, locking, lists, and a number of
+ other features.
+
+Package: libpmemobj-dev
+Section: libdevel
+Architecture: any
+Depends: libpmemobj (=\${binary:Version}), libpmem-dev, \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmemobj
+ libpmemobj turns a persistent memory file into a flexible object store,
+ supporting transactions, memory management, locking, lists, and a number of
+ other features.
+ .
+ This package contains libraries and header files used for linking programs
+ against libpmemobj.
+
+Package: libpmempool
+Architecture: any
+Depends: libpmem (=\${binary:Version}), \${shlibs:Depends}, \${misc:Depends}
+Description: Persistent Memory pool management support library
+ libpmempool provides a set of utilities for management, diagnostics and repair
+ of persistent memory pools. A pool in this context means a pmemobj pool,
+ pmemblk pool, pmemlog pool or BTT layout, independent of the underlying
+ storage. The libpmempool is for applications that need high reliability or
+ built-in troubleshooting. It may be useful for testing and debugging purposes
+ also.
+
+Package: libpmempool-dev
+Section: libdevel
+Architecture: any
+Depends: libpmempool (=\${binary:Version}), libpmem-dev, \${shlibs:Depends}, \${misc:Depends}
+Description: Development files for libpmempool
+ libpmempool provides a set of utilities for management, diagnostics and repair
+ of persistent memory pools.
+ .
+ This package contains libraries and header files used for linking programs
+ against libpmempool.
+
+Package: $PACKAGE_NAME-dbg
+Section: debug
+Priority: optional
+Architecture: any
+Depends: libpmem (=\${binary:Version}), libpmemblk (=\${binary:Version}), libpmemlog (=\${binary:Version}), libpmemobj (=\${binary:Version}), libpmempool (=\${binary:Version}), \${misc:Depends}
+Description: Debug symbols for PMDK libraries
+ Debug symbols for all PMDK libraries.
+
+Package: pmempool
+Section: misc
+Architecture: any
+Priority: optional
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: utility for management and off-line analysis of PMDK memory pools
+ This utility is a standalone tool that manages Persistent Memory pools
+ created by PMDK libraries. It provides a set of utilities for
+ administration and diagnostics of Persistent Memory pools. Pmempool may be
+ useful for troubleshooting by system administrators and users of the
+ applications based on PMDK libraries.
+
+Package: pmreorder
+Section: misc
+Architecture: any
+Priority: optional
+Depends: \${shlibs:Depends}, \${misc:Depends}
+Description: tool to parse and replay pmemcheck logs
+ Pmreorder is tool that parses and replays log of operations collected by
+ pmemcheck -- a atandalone tool which is a collection of python scripts designed
+ to parse and replay operations logged by pmemcheck - a persistent memory
+ checking tool. Pmreorder performs the store reordering between persistent
+ memory barriers - a sequence of flush-fence operations. It uses a
+ consistency checking routine provided in the command line options to check
+ whether files are in a consistent state.
+EOF
+
+cp LICENSE debian/copyright
+
+if [ -n "$NDCTL_ENABLE" ]; then
+ pass_ndctl_enable="NDCTL_ENABLE=$NDCTL_ENABLE"
+else
+ pass_ndctl_enable=""
+fi
+
+cat << EOF > debian/rules
+#!/usr/bin/make -f
+#export DH_VERBOSE=1
+%:
+ dh \$@
+
+override_dh_strip:
+ dh_strip --dbg-package=$PACKAGE_NAME-dbg
+
+override_dh_auto_build:
+ dh_auto_build -- EXPERIMENTAL=${EXPERIMENTAL} prefix=/$PREFIX libdir=/$LIB_DIR includedir=/$INC_DIR docdir=/$DOC_DIR man1dir=/$MAN1_DIR man3dir=/$MAN3_DIR man5dir=/$MAN5_DIR man7dir=/$MAN7_DIR sysconfdir=/etc bashcompdir=/usr/share/bash-completion/completions NORPATH=1 ${pass_ndctl_enable} SRCVERSION=$SRCVERSION PMEM2_INSTALL=${PMEM2_INSTALL}
+
+override_dh_auto_install:
+ dh_auto_install -- EXPERIMENTAL=${EXPERIMENTAL} prefix=/$PREFIX libdir=/$LIB_DIR includedir=/$INC_DIR docdir=/$DOC_DIR man1dir=/$MAN1_DIR man3dir=/$MAN3_DIR man5dir=/$MAN5_DIR man7dir=/$MAN7_DIR sysconfdir=/etc bashcompdir=/usr/share/bash-completion/completions NORPATH=1 ${pass_ndctl_enable} SRCVERSION=$SRCVERSION PMEM2_INSTALL=${PMEM2_INSTALL}
+ find -path './debian/*usr/share/man/man*/*.gz' -exec gunzip {} \;
+
+override_dh_install:
+ mkdir -p debian/tmp/usr/share/pmdk/
+ cp utils/pmdk.magic debian/tmp/usr/share/pmdk/
+ dh_install
+
+${CHECK_CMD}
+EOF
+
+chmod +x debian/rules
+
+mkdir debian/source
+
+ITP_BUG_EXCUSE="# This is our first package but we do not want to upload it yet.
+# Please refer to Debian Developer's Reference section 5.1 (New packages) for details:
+# https://www.debian.org/doc/manuals/developers-reference/pkgs.html#newpackage"
+
+cat << EOF > debian/source/format
+3.0 (quilt)
+EOF
+
+cat << EOF > debian/libpmem.install
+$LIB_DIR/libpmem.so.*
+usr/share/pmdk/pmdk.magic
+$MAN5_DIR/poolset.5
+EOF
+
+cat $MAGIC_INSTALL > debian/libpmem.postinst
+sed -i '1s/.*/\#\!\/bin\/bash/' debian/libpmem.postinst
+echo $'\n#DEBHELPER#\n' >> debian/libpmem.postinst
+cat $MAGIC_UNINSTALL > debian/libpmem.prerm
+sed -i '1s/.*/\#\!\/bin\/bash/' debian/libpmem.prerm
+echo $'\n#DEBHELPER#\n' >> debian/libpmem.prerm
+
+cat << EOF > debian/libpmem.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmem: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmem-dev.install
+$LIB_DIR/pmdk_debug/libpmem.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmem.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmem.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmem.so
+$LIB_DIR/pkgconfig/libpmem.pc
+$INC_DIR/libpmem.h
+$MAN7_DIR/libpmem.7
+$MAN3_DIR/pmem_*.3
+EOF
+
+cat << EOF > debian/libpmem-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+# pmdk provides second set of libraries for debugging.
+# These are in /usr/lib/$arch/pmdk_dbg/, but still trigger ldconfig.
+# Related issue: https://github.com/pmem/issues/issues/841
+libpmem-dev: package-has-unnecessary-activation-of-ldconfig-trigger
+
+EOF
+
+cat << EOF > debian/libpmemblk.install
+$LIB_DIR/libpmemblk.so.*
+EOF
+
+cat << EOF > debian/libpmemblk.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmemblk: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmemblk-dev.install
+$LIB_DIR/pmdk_debug/libpmemblk.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemblk.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemblk.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmemblk.so
+$LIB_DIR/pkgconfig/libpmemblk.pc
+$INC_DIR/libpmemblk.h
+$MAN7_DIR/libpmemblk.7
+$MAN3_DIR/pmemblk_*.3
+EOF
+
+cat << EOF > debian/libpmemblk-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+# pmdk provides second set of libraries for debugging.
+# These are in /usr/lib/$arch/pmdk_dbg/, but still trigger ldconfig.
+# Related issue: https://github.com/pmem/issues/issues/841
+libpmemblk-dev: package-has-unnecessary-activation-of-ldconfig-trigger
+EOF
+
+cat << EOF > debian/libpmemlog.install
+$LIB_DIR/libpmemlog.so.*
+EOF
+
+cat << EOF > debian/libpmemlog.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmemlog: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmemlog-dev.install
+$LIB_DIR/pmdk_debug/libpmemlog.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemlog.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemlog.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmemlog.so
+$LIB_DIR/pkgconfig/libpmemlog.pc
+$INC_DIR/libpmemlog.h
+$MAN7_DIR/libpmemlog.7
+$MAN3_DIR/pmemlog_*.3
+EOF
+
+cat << EOF > debian/libpmemlog-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+# pmdk provides second set of libraries for debugging.
+# These are in /usr/lib/$arch/pmdk_dbg/, but still trigger ldconfig.
+# Related issue: https://github.com/pmem/issues/issues/841
+libpmemlog-dev: package-has-unnecessary-activation-of-ldconfig-trigger
+EOF
+
+cat << EOF > debian/libpmemobj.install
+$LIB_DIR/libpmemobj.so.*
+EOF
+
+cat << EOF > debian/libpmemobj.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmemobj: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmemobj-dev.install
+$LIB_DIR/pmdk_debug/libpmemobj.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemobj.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmemobj.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmemobj.so
+$LIB_DIR/pkgconfig/libpmemobj.pc
+$INC_DIR/libpmemobj.h
+$INC_DIR/libpmemobj/*.h
+$MAN7_DIR/libpmemobj.7
+$MAN3_DIR/pmemobj_*.3
+$MAN3_DIR/pobj_*.3
+$MAN3_DIR/oid_*.3
+$MAN3_DIR/toid*.3
+$MAN3_DIR/direct_*.3
+$MAN3_DIR/d_r*.3
+$MAN3_DIR/tx_*.3
+EOF
+
+cat << EOF > debian/libpmemobj-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+# pmdk provides second set of libraries for debugging.
+# These are in /usr/lib/$arch/pmdk_dbg/, but still trigger ldconfig.
+# Related issue: https://github.com/pmem/issues/issues/841
+libpmemobj-dev: package-has-unnecessary-activation-of-ldconfig-trigger
+EOF
+
+cat << EOF > debian/libpmempool.install
+$LIB_DIR/libpmempool.so.*
+EOF
+
+cat << EOF > debian/libpmempool.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+libpmempool: package-name-doesnt-match-sonames
+EOF
+
+cat << EOF > debian/libpmempool-dev.install
+$LIB_DIR/pmdk_debug/libpmempool.a $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmempool.so $LIB_DIR/pmdk_dbg/
+$LIB_DIR/pmdk_debug/libpmempool.so.* $LIB_DIR/pmdk_dbg/
+$LIB_DIR/libpmempool.so
+$LIB_DIR/pkgconfig/libpmempool.pc
+$INC_DIR/libpmempool.h
+$MAN7_DIR/libpmempool.7
+$MAN3_DIR/pmempool_*.3
+EOF
+
+cat << EOF > debian/libpmempool-dev.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+# The following warnings are triggered by a bug in debhelper:
+# https://bugs.debian.org/204975
+postinst-has-useless-call-to-ldconfig
+postrm-has-useless-call-to-ldconfig
+# We do not want to compile with -O2 for debug version
+hardening-no-fortify-functions $LIB_DIR/pmdk_dbg/*
+# pmdk provides second set of libraries for debugging.
+# These are in /usr/lib/$arch/pmdk_dbg/, but still trigger ldconfig.
+# Related issue: https://github.com/pmem/issues/issues/841
+libpmempool-dev: package-has-unnecessary-activation-of-ldconfig-trigger
+EOF
+
+cat << EOF > debian/$PACKAGE_NAME-dbg.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+EOF
+
+cat << EOF > debian/pmempool.install
+usr/bin/pmempool
+$MAN1_DIR/pmempool.1
+$MAN1_DIR/pmempool-*.1
+usr/share/bash-completion/completions/pmempool
+EOF
+
+cat << EOF > debian/pmempool.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+EOF
+
+cat << EOF > debian/pmreorder.install
+usr/bin/pmreorder
+usr/share/pmreorder/*.py
+$MAN1_DIR/pmreorder.1
+EOF
+
+cat << EOF > debian/pmreorder.lintian-overrides
+$ITP_BUG_EXCUSE
+new-package-should-close-itp-bug
+EOF
+
+# librpmem & rpmemd
+if [ "${BUILD_RPMEM}" = "y" -a "${RPMEM_DPKG}" = "y" ]
+then
+ append_rpmem_control;
+ rpmem_install_triggers_overrides;
+fi
+
+# libpmem2
+if [ "${PMEM2_INSTALL}" == "y" ]
+then
+ append_libpmem2_control;
+ libpmem2_install_triggers_overrides;
+fi
+
+# daxio
+if [ "${NDCTL_ENABLE}" != "n" ]
+then
+ append_daxio_control;
+ daxio_install_triggers_overrides;
+fi
+
+# Convert ChangeLog to debian format
+CHANGELOG_TMP=changelog.tmp
+dch --create --empty --package $PACKAGE_NAME -v $PACKAGE_VERSION-$PACKAGE_RELEASE -M -c $CHANGELOG_TMP
+touch debian/changelog
+head -n1 $CHANGELOG_TMP >> debian/changelog
+echo "" >> debian/changelog
+convert_changelog ChangeLog >> debian/changelog
+echo "" >> debian/changelog
+tail -n1 $CHANGELOG_TMP >> debian/changelog
+rm $CHANGELOG_TMP
+
+# This is our first release but we do
+debuild --preserve-envvar=EXTRA_CFLAGS_RELEASE \
+ --preserve-envvar=EXTRA_CFLAGS_DEBUG \
+ --preserve-envvar=EXTRA_CFLAGS \
+ --preserve-envvar=EXTRA_CXXFLAGS \
+ --preserve-envvar=EXTRA_LDFLAGS \
+ --preserve-envvar=NDCTL_ENABLE \
+ -us -uc -b
+
+cd $OLD_DIR
+
+find $WORKING_DIR -name "*.deb"\
+ -or -name "*.dsc"\
+ -or -name "*.changes"\
+ -or -name "*.orig.tar.gz"\
+ -or -name "*.debian.tar.gz" | while read FILE
+do
+ mv -v $FILE $OUT_DIR/
+done
+
+exit 0
diff --git a/src/pmdk/utils/build-rpm.sh b/src/pmdk/utils/build-rpm.sh
new file mode 100755
index 000000000..759a1fe1c
--- /dev/null
+++ b/src/pmdk/utils/build-rpm.sh
@@ -0,0 +1,263 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2020, Intel Corporation
+
+#
+# build-rpm.sh - Script for building rpm packages
+#
+
+set -e
+
+SCRIPT_DIR=$(dirname $0)
+source $SCRIPT_DIR/pkg-common.sh
+
+check_tool rpmbuild
+check_file $SCRIPT_DIR/pkg-config.sh
+source $SCRIPT_DIR/pkg-config.sh
+
+#
+# usage -- print usage message and exit
+#
+usage()
+{
+ [ "$1" ] && echo Error: $1
+ cat >&2 <<EOF
+Usage: $0 [ -h ] -t version-tag -s source-dir -w working-dir -o output-dir
+ [ -d distro ] [ -e build-experimental ] [ -c run-check ]
+ [ -r build-rpmem ] [ -n with-ndctl ] [ -f testconfig-file ]
+
+-h print this help message
+-t version-tag source version tag
+-s source-dir source directory
+-w working-dir working directory
+-o output-dir output directory
+-d distro Linux distro name
+-e build-experimental build experimental packages
+-c run-check run package check
+-r build-rpmem build librpmem and rpmemd packages
+-n with-ndctl build with libndctl
+-f testconfig-file custom testconfig.sh
+EOF
+ exit 1
+}
+
+#
+# command-line argument processing...
+#
+args=`getopt he:c:r:n:t:d:s:w:o:f: $*`
+[ $? != 0 ] && usage
+set -- $args
+for arg
+do
+ receivetype=auto
+ case "$arg"
+ in
+ -e)
+ EXPERIMENTAL="$2"
+ shift 2
+ ;;
+ -c)
+ BUILD_PACKAGE_CHECK="$2"
+ shift 2
+ ;;
+ -f)
+ TEST_CONFIG_FILE="$2"
+ shift 2
+ ;;
+ -r)
+ BUILD_RPMEM="$2"
+ shift 2
+ ;;
+ -n)
+ NDCTL_ENABLE="$2"
+ shift 2
+ ;;
+ -t)
+ PACKAGE_VERSION_TAG="$2"
+ shift 2
+ ;;
+ -s)
+ SOURCE="$2"
+ shift 2
+ ;;
+ -w)
+ WORKING_DIR="$2"
+ shift 2
+ ;;
+ -o)
+ OUT_DIR="$2"
+ shift 2
+ ;;
+ -d)
+ DISTRO="$2"
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ esac
+done
+
+# check for mandatory arguments
+if [ -z "$PACKAGE_VERSION_TAG" -o -z "$SOURCE" -o -z "$WORKING_DIR" -o -z "$OUT_DIR" ]
+then
+ error "Mandatory arguments missing"
+ usage
+fi
+
+# detected distro or defined in cmd
+if [ -z "${DISTRO}" ]
+then
+ OS=$(get_os)
+ if [ "$OS" != "1" ]
+ then
+ echo "Detected OS: $OS"
+ DISTRO=$OS
+ else
+ error "Unknown distribution"
+ exit 1
+ fi
+fi
+
+if [ "$EXTRA_CFLAGS_RELEASE" = "" ]; then
+ export EXTRA_CFLAGS_RELEASE="-ggdb -fno-omit-frame-pointer"
+fi
+
+PMEM2_INSTALL="y"
+
+LIBFABRIC_MIN_VERSION=1.4.2
+NDCTL_MIN_VERSION=60.1
+
+RPMBUILD_OPTS=( )
+PACKAGE_VERSION=$(get_version $PACKAGE_VERSION_TAG)
+
+if [ -z "$PACKAGE_VERSION" ]
+then
+ error "Can not parse version from '${PACKAGE_VERSION_TAG}'"
+ exit 1
+fi
+
+PACKAGE_SOURCE=${PACKAGE_NAME}-${PACKAGE_VERSION}
+SOURCE=$PACKAGE_NAME
+PACKAGE_TARBALL=$PACKAGE_SOURCE.tar.gz
+RPM_SPEC_FILE=$PACKAGE_SOURCE/$PACKAGE_NAME.spec
+MAGIC_INSTALL=$PACKAGE_SOURCE/utils/magic-install.sh
+MAGIC_UNINSTALL=$PACKAGE_SOURCE/utils/magic-uninstall.sh
+OLDPWD=$PWD
+
+[ -d $WORKING_DIR ] || mkdir -v $WORKING_DIR
+[ -d $OUT_DIR ] || mkdir $OUT_DIR
+
+cd $WORKING_DIR
+
+check_dir $SOURCE
+mv $SOURCE $PACKAGE_SOURCE
+
+if [ "$DISTRO" = "SLES_like" ]
+then
+ RPM_LICENSE="BSD-3-Clause"
+ RPM_GROUP_SYS_BASE="System\/Base"
+ RPM_GROUP_SYS_LIBS="System\/Libraries"
+ RPM_GROUP_DEV_LIBS="Development\/Libraries\/C and C++"
+ RPM_PKG_NAME_SUFFIX="1"
+ RPM_MAKE_FLAGS="BINDIR=""%_bindir"" NORPATH=1"
+ RPM_MAKE_INSTALL="%fdupes %{buildroot}\/%{_prefix}"
+else
+ RPM_LICENSE="BSD"
+ RPM_GROUP_SYS_BASE="System Environment\/Base"
+ RPM_GROUP_SYS_LIBS="System Environment\/Libraries"
+ RPM_GROUP_DEV_LIBS="Development\/Libraries"
+ RPM_PKG_NAME_SUFFIX=""
+ RPM_MAKE_FLAGS="NORPATH=1"
+ RPM_MAKE_INSTALL=""
+fi
+
+#
+# Create parametrized spec file required by rpmbuild.
+# Most of variables are set in pkg-config.sh file in order to
+# keep descriptive values separately from this script.
+#
+sed -e "s/__VERSION__/$PACKAGE_VERSION/g" \
+ -e "s/__LICENSE__/$RPM_LICENSE/g" \
+ -e "s/__PACKAGE_MAINTAINER__/$PACKAGE_MAINTAINER/g" \
+ -e "s/__PACKAGE_SUMMARY__/$PACKAGE_SUMMARY/g" \
+ -e "s/__GROUP_SYS_BASE__/$RPM_GROUP_SYS_BASE/g" \
+ -e "s/__GROUP_SYS_LIBS__/$RPM_GROUP_SYS_LIBS/g" \
+ -e "s/__GROUP_DEV_LIBS__/$RPM_GROUP_DEV_LIBS/g" \
+ -e "s/__PKG_NAME_SUFFIX__/$RPM_PKG_NAME_SUFFIX/g" \
+ -e "s/__MAKE_FLAGS__/$RPM_MAKE_FLAGS/g" \
+ -e "s/__MAKE_INSTALL_FDUPES__/$RPM_MAKE_INSTALL/g" \
+ -e "s/__LIBFABRIC_MIN_VER__/$LIBFABRIC_MIN_VERSION/g" \
+ -e "s/__NDCTL_MIN_VER__/$NDCTL_MIN_VERSION/g" \
+ $OLDPWD/$SCRIPT_DIR/pmdk.spec.in > $RPM_SPEC_FILE
+
+if [ "$DISTRO" = "SLES_like" ]
+then
+ sed -i '/^#.*bugzilla.redhat/d' $RPM_SPEC_FILE
+fi
+
+# do not split on space
+IFS=$'\n'
+
+# experimental features
+if [ "${EXPERIMENTAL}" = "y" ]
+then
+ # no experimental features for now
+ RPMBUILD_OPTS+=( )
+fi
+
+# libpmem2
+if [ "${PMEM2_INSTALL}" == "y" ]
+then
+ RPMBUILD_OPTS+=(--define "_pmem2_install 1")
+fi
+
+# librpmem & rpmemd
+if [ "${BUILD_RPMEM}" = "y" ]
+then
+ RPMBUILD_OPTS+=(--with fabric)
+else
+ RPMBUILD_OPTS+=(--without fabric)
+fi
+
+# daxio & RAS
+if [ "${NDCTL_ENABLE}" = "n" ]
+then
+ RPMBUILD_OPTS+=(--without ndctl)
+else
+ RPMBUILD_OPTS+=(--with ndctl)
+fi
+
+# use specified testconfig file or default
+if [[( -n "${TEST_CONFIG_FILE}") && ( -f "$TEST_CONFIG_FILE" ) ]]
+then
+ echo "Test config file: $TEST_CONFIG_FILE"
+ RPMBUILD_OPTS+=(--define "_testconfig $TEST_CONFIG_FILE")
+else
+ echo -e "Test config file $TEST_CONFIG_FILE does not exist.\n"\
+ "Default test config will be used."
+fi
+
+# run make check or not
+if [ "${BUILD_PACKAGE_CHECK}" == "n" ]
+then
+ RPMBUILD_OPTS+=(--define "_skip_check 1")
+fi
+
+tar zcf $PACKAGE_TARBALL $PACKAGE_SOURCE
+
+# Create directory structure for rpmbuild
+mkdir -v BUILD SPECS
+
+echo "opts: ${RPMBUILD_OPTS[@]}"
+
+rpmbuild --define "_topdir `pwd`"\
+ --define "_rpmdir ${OUT_DIR}"\
+ --define "_srcrpmdir ${OUT_DIR}"\
+ -ta $PACKAGE_TARBALL \
+ ${RPMBUILD_OPTS[@]}
+
+echo "Building rpm packages done"
+
+exit 0
diff --git a/src/pmdk/utils/check-area.sh b/src/pmdk/utils/check-area.sh
new file mode 100755
index 000000000..911556b91
--- /dev/null
+++ b/src/pmdk/utils/check-area.sh
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2018-2020, Intel Corporation
+
+#
+# Finds applicable area name for specified commit id.
+#
+
+if [ -z "$1" ]; then
+ echo "Missing commit id argument."
+ exit 1
+fi
+
+files=$(git show $1 --format=oneline --name-only | grep -v -e "$1")
+
+git show -q $1 | cat
+
+echo
+echo "Modified files:"
+echo "$files"
+
+function categorize() {
+ category=$1
+ shift
+ cat_files=`echo "$files" | grep $*`
+
+ if [ -n "${cat_files}" ]; then
+ echo "$category"
+ files=`echo "$files" | grep -v $*`
+ fi
+}
+
+echo
+echo "Areas computed basing on the list of modified files: (see utils/check-area.sh for full algorithm)"
+
+categorize core -e "^src/core/"
+categorize pmem -e "^src/libpmem/" -e "^src/include/libpmem.h"
+categorize pmem2 -e "^src/libpmem2/" -e "^src/include/libpmem2.h"
+categorize rpmem -e "^src/librpmem/" -e "^src/include/librpmem.h" -e "^src/tools/rpmemd/" -e "^src/rpmem_common/"
+categorize log -e "^src/libpmemlog/" -e "^src/include/libpmemlog.h"
+categorize blk -e "^src/libpmemblk/" -e "^src/include/libpmemblk.h"
+categorize obj -e "^src/libpmemobj/" -e "^src/include/libpmemobj.h" -e "^src/include/libpmemobj/"
+categorize pool -e "^src/libpmempool/" -e "^src/include/libpmempool.h" -e "^src/tools/pmempool/"
+categorize benchmark -e "^src/benchmarks/"
+categorize examples -e "^src/examples/"
+categorize daxio -e "^src/tools/daxio/"
+categorize pmreorder -e "^src/tools/pmreorder/"
+categorize test -e "^src/test/"
+categorize doc -e "^doc/" -e ".md\$" -e "^ChangeLog" -e "README"
+categorize common -e "^src/common/" \
+ -e "^utils/" \
+ -e ".inc\$" \
+ -e ".yml\$" \
+ -e ".gitattributes" \
+ -e ".gitignore" \
+ -e "^.mailmap\$" \
+ -e "^src/PMDK.sln\$" \
+ -e "Makefile\$" \
+ -e "^src/freebsd/" \
+ -e "^src/windows/" \
+ -e "^src/include/pmemcompat.h"
+
+echo
+echo "If the above list contains more than 1 entry, please consider splitting"
+echo "your change into more commits, unless those changes don't make sense "
+echo "individually (they do not build, tests do not pass, etc)."
+echo "For example, it's perfectly fine to use 'obj' prefix for one commit that"
+echo "changes libpmemobj source code, its tests and documentation."
+
+if [ -n "$files" ]; then
+ echo
+ echo "Uncategorized files:"
+ echo "$files"
+fi
diff --git a/src/pmdk/utils/check-commit.sh b/src/pmdk/utils/check-commit.sh
new file mode 100755
index 000000000..3985e40c3
--- /dev/null
+++ b/src/pmdk/utils/check-commit.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# Used to check whether all the commit messages in a pull request
+# follow the GIT/PMDK guidelines.
+#
+# usage: ./check-commit.sh commit
+#
+
+if [ -z "$1" ]; then
+ echo "Usage: check-commit.sh commit-id"
+ exit 1
+fi
+
+echo "Checking $1"
+
+subject=$(git log --format="%s" -n 1 $1)
+
+if [[ $subject =~ ^Merge.* ]]; then
+ # skip
+ exit 0
+fi
+
+if [[ $subject =~ ^Revert.* ]]; then
+ # skip
+ exit 0
+fi
+
+# valid area names
+AREAS="pmem\|pmem2\|rpmem\|log\|blk\|obj\|pool\|test\|benchmark\|examples\|doc\|core\|common\|daxio\|pmreorder"
+
+prefix=$(echo $subject | sed -n "s/^\($AREAS\)\:.*/\1/p")
+
+if [ "$prefix" = "" ]; then
+ echo "FAIL: subject line in commit message does not contain valid area name"
+ echo
+ `dirname $0`/check-area.sh $1
+ exit 1
+fi
+
+commit_len=$(git log --format="%s%n%b" -n 1 $1 | wc -L)
+
+if [ $commit_len -gt 73 ]; then
+ echo "FAIL: commit message exceeds 72 chars per line (commit_len)"
+ echo
+ git log -n 1 $1 | cat
+ exit 1
+fi
diff --git a/src/pmdk/utils/check-commits.sh b/src/pmdk/utils/check-commits.sh
new file mode 100755
index 000000000..762db22db
--- /dev/null
+++ b/src/pmdk/utils/check-commits.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# Used to check whether all the commit messages in a pull request
+# follow the GIT/PMDK guidelines.
+#
+# usage: ./check-commits.sh [range]
+#
+
+if [ -z "$1" ]; then
+ # on CI run this check only for pull requests
+ if [ -n "$CI_REPO_SLUG" ]; then
+ if [[ "$CI_REPO_SLUG" != "$GITHUB_REPO" \
+ || $CI_EVENT_TYPE != "pull_request" ]];
+ then
+ echo "SKIP: $0 can only be executed for pull requests to $GITHUB_REPO"
+ exit 0
+ fi
+ fi
+ # CI_COMMIT_RANGE can be invalid for force pushes - use another
+ # method to determine the list of commits
+ if [[ $(git rev-list $CI_COMMIT_RANGE 2>/dev/null) || -n "$CI_COMMIT_RANGE" ]]; then
+ MERGE_BASE=$(echo $CI_COMMIT_RANGE | cut -d. -f1)
+ [ -z $MERGE_BASE ] && \
+ MERGE_BASE=$(git log --pretty="%cN:%H" | grep GitHub | head -n1 | cut -d: -f2)
+ RANGE=$MERGE_BASE..$CI_COMMIT
+ else
+ MERGE_BASE=$(git log --pretty="%cN:%H" | grep GitHub | head -n1 | cut -d: -f2)
+ RANGE=$MERGE_BASE..HEAD
+ fi
+else
+ RANGE="$1"
+fi
+
+COMMITS=$(git log --pretty=%H $RANGE)
+
+set -e
+
+for commit in $COMMITS; do
+ `dirname $0`/check-commit.sh $commit
+done
diff --git a/src/pmdk/utils/check-manpage b/src/pmdk/utils/check-manpage
new file mode 100755
index 000000000..d0c0d4d2e
--- /dev/null
+++ b/src/pmdk/utils/check-manpage
@@ -0,0 +1,62 @@
+#!/bin/bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019, Intel Corporation
+
+# check-manpage -- a tool to check a single man page against errors
+#
+# While it can handle multiple files, it's recommended to use
+# check-manpages instead.
+set -e
+
+check_link()
+{
+ [ $(wc -l <"$file") = 1 ] ||
+ { echo ".so link isn't the only line" && return; }
+ link=$(cat "$file")
+ link=${link#.so }
+ [ "${link##*/}" = "$link" ] ||
+ grep -q '^\.so man\([0-9]\)/[a-z0-9+_-]\+\.\1$' "$file" ||
+ { echo ".so link directory is not matching manX" && return; }
+ [ -e "${link##*/}" ] ||
+ { echo ".so link target doesn't exist: ${link##*/}" && return; }
+}
+
+for m in "$@"; do
+ dir="$(dirname $m)"
+ file="$(basename $m)"
+ [ -n "$dir" ] && pushd "$dir" >/dev/null
+
+ if grep -q '^\.so' "$file"; then
+ err=$(check_link)
+ [ -z "$err" ] || {
+ echo >&2 "$file: $err"
+ FAILED=1
+ }
+ popd >/dev/null 2>/dev/null
+ continue
+ fi
+
+ # man can emit warnings and errors. Even non-fatal errors are normally
+ # suppressed if a pager is in use (ie, all interactive usage). Common
+ # messages include an unknown macro, an unbreakable line, etc.
+ err=$(MANWIDTH=80 man --warnings -E UTF-8 -l -Tutf8 -Z "$file" 2>&1 >/dev/null|
+ grep -v 'cannot adjust line' || true)
+ [ -z "$err" ] || {
+ echo >&2 "$file: $err"
+ FAILED=1
+ }
+
+ # If a "NAME" section exists, call lexgrog to see if it's properly
+ # formatted.
+ if grep -q '^\.SH NAME' "$file"; then
+ if ! lexgrog "$file" >/dev/null; then
+ # lexgrog doesn't give any interesting messages.
+ echo 2>&1 "lexgrog failed on $file"
+ FAILED=1
+ fi
+ fi
+
+ popd >/dev/null 2>/dev/null
+done
+
+exit $FAILED
diff --git a/src/pmdk/utils/check-manpages b/src/pmdk/utils/check-manpages
new file mode 100755
index 000000000..415db124c
--- /dev/null
+++ b/src/pmdk/utils/check-manpages
@@ -0,0 +1,16 @@
+#!/bin/bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019-2020, Intel Corporation
+
+# check-manpages -- a tool to test against some manpage errors
+
+MANS="$*"
+[ -n "$MANS" ] || MANS="$(find doc -name '*.1' -o -name '*.3' -o -name '*.5' -o -name '*.7')"
+[ -n "$MANS" ] || { echo >&2 "No man pages given, and none found in doc/"; exit 1;}
+
+for page in $MANS;do
+ if [ "${page/rpmem/}" != "$page" ] && [ "$BUILD_RPMEM" != "y" ]; then
+ continue
+ fi
+ echo $page
+done | xargs -P `nproc` -n1 -- utils/check-manpage
diff --git a/src/pmdk/utils/check-os.sh b/src/pmdk/utils/check-os.sh
new file mode 100755
index 000000000..64d371c13
--- /dev/null
+++ b/src/pmdk/utils/check-os.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2019, Intel Corporation
+
+#
+# Used to check if there are no banned functions in .o file
+#
+# usage: ./check-os.sh [os.h path] [.o file] [.c file]
+
+EXCLUDE="os_posix|os_thread_posix"
+if [[ $2 =~ $EXCLUDE ]]; then
+ echo "skip $2"
+ exit 0
+fi
+
+symbols=$(nm --demangle --undefined-only --format=posix $2 | sed 's/ U *//g')
+functions=$(cat $1 | tr '\n' '|')
+functions=${functions%?} # remove trailing | character
+out=$(
+ for sym in $symbols
+ do
+ grep -wE $functions <<<"$sym"
+ done | sed 's/$/\(\)/g')
+
+[[ ! -z $out ]] &&
+ echo -e "`pwd`/$3:1: non wrapped function(s):\n$out\nplease use os wrappers" &&
+ rm -f $2 && # remove .o file as it don't match requirements
+ exit 1
+
+exit 0
diff --git a/src/pmdk/utils/check-shebang.sh b/src/pmdk/utils/check-shebang.sh
new file mode 100755
index 000000000..1051d178b
--- /dev/null
+++ b/src/pmdk/utils/check-shebang.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2019, Intel Corporation
+#
+# utils/check-shebang.sh -- interpreter directive check script
+#
+set -e
+
+err_count=0
+
+for file in $@ ; do
+ [ ! -f $file ] && continue
+ SHEBANG=`head -n1 $file | cut -d" " -f1`
+ [ "${SHEBANG:0:2}" != "#!" ] && continue
+ if [ "$SHEBANG" != "#!/usr/bin/env" -a $SHEBANG != "#!/bin/sh" ]; then
+ INTERP=`echo $SHEBANG | rev | cut -d"/" -f1 | rev`
+ echo "$file:1: error: invalid interpreter directive:" >&2
+ echo " (is: \"$SHEBANG\", should be: \"#!/usr/bin/env $INTERP\")" >&2
+ ((err_count+=1))
+ fi
+done
+
+if [ "$err_count" == "0" ]; then
+ echo "Interpreter directives are OK."
+else
+ echo "Found $err_count errors in interpreter directives!" >&2
+ err_count=1
+fi
+
+exit $err_count
diff --git a/src/pmdk/utils/check_license/.gitignore b/src/pmdk/utils/check_license/.gitignore
new file mode 100644
index 000000000..8891a7f15
--- /dev/null
+++ b/src/pmdk/utils/check_license/.gitignore
@@ -0,0 +1 @@
+check-license
diff --git a/src/pmdk/utils/check_license/check-headers.sh b/src/pmdk/utils/check_license/check-headers.sh
new file mode 100755
index 000000000..f79453bd3
--- /dev/null
+++ b/src/pmdk/utils/check_license/check-headers.sh
@@ -0,0 +1,192 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+# check-headers.sh - check copyright and license in source files
+
+SELF=$0
+
+function usage() {
+ echo "Usage: $SELF <source_root_path> <license_tag> [-h|-v|-a]"
+ echo " -h, --help this help message"
+ echo " -v, --verbose verbose mode"
+ echo " -a, --all check all files (only modified files are checked by default)"
+}
+
+if [ "$#" -lt 2 ]; then
+ usage >&2
+ exit 2
+fi
+
+SOURCE_ROOT=$1
+shift
+LICENSE=$1
+shift
+
+PATTERN=`mktemp`
+TMP=`mktemp`
+TMP2=`mktemp`
+TEMPFILE=`mktemp`
+rm -f $PATTERN $TMP $TMP2
+
+if [ "$1" == "-h" -o "$1" == "--help" ]; then
+ usage
+ exit 0
+fi
+
+export GIT="git -C ${SOURCE_ROOT}"
+$GIT rev-parse || exit 1
+
+if [ -f $SOURCE_ROOT/.git/shallow ]; then
+ SHALLOW_CLONE=1
+ echo
+ echo "Warning: This is a shallow clone. Checking dates in copyright headers"
+ echo " will be skipped in case of files that have no history."
+ echo
+else
+ SHALLOW_CLONE=0
+fi
+
+VERBOSE=0
+CHECK_ALL=0
+while [ "$1" != "" ]; do
+ case $1 in
+ -v|--verbose)
+ VERBOSE=1
+ ;;
+ -a|--all)
+ CHECK_ALL=1
+ ;;
+ esac
+ shift
+done
+
+if [ $CHECK_ALL -eq 0 ]; then
+ CURRENT_COMMIT=$($GIT log --pretty=%H -1)
+ MERGE_BASE=$($GIT merge-base HEAD origin/master 2>/dev/null)
+ [ -z $MERGE_BASE ] && \
+ MERGE_BASE=$($GIT log --pretty="%cN:%H" | grep GitHub | head -n1 | cut -d: -f2)
+ [ -z $MERGE_BASE -o "$CURRENT_COMMIT" = "$MERGE_BASE" ] && \
+ CHECK_ALL=1
+fi
+
+if [ $CHECK_ALL -eq 1 ]; then
+ echo "Checking copyright headers of all files..."
+ GIT_COMMAND="ls-tree -r --name-only HEAD"
+else
+ if [ $VERBOSE -eq 1 ]; then
+ echo
+ echo "Warning: will check copyright headers of modified files only,"
+ echo " in order to check all files issue the following command:"
+ echo " $ $SELF <source_root_path> <license_tag> -a"
+ echo " (e.g.: $ $SELF $SOURCE_ROOT $LICENSE -a)"
+ echo
+ fi
+ echo "Checking copyright headers of modified files only..."
+ GIT_COMMAND="diff --name-only $MERGE_BASE $CURRENT_COMMIT"
+fi
+
+FILES=$($GIT $GIT_COMMAND | ${SOURCE_ROOT}/utils/check_license/file-exceptions.sh | \
+ grep -E -e '*\.[chs]$' -e '*\.[ch]pp$' -e '*\.sh$' \
+ -e '*\.py$' -e '*\.link$' -e 'Makefile*' -e 'TEST*' \
+ -e '/common.inc$' -e '/match$' -e '/check_whitespace$' \
+ -e 'LICENSE$' -e 'CMakeLists.txt$' -e '*\.cmake$' | \
+ xargs)
+
+RV=0
+for file in $FILES ; do
+ # The src_path is a path which should be used in every command except git.
+ # git is called with -C flag so filepaths should be relative to SOURCE_ROOT
+ src_path="${SOURCE_ROOT}/$file"
+ [ ! -f $src_path ] && continue
+ # ensure that file is UTF-8 encoded
+ ENCODING=`file -b --mime-encoding $src_path`
+ iconv -f $ENCODING -t "UTF-8" $src_path > $TEMPFILE
+
+ if ! grep -q "SPDX-License-Identifier: $LICENSE" $src_path; then
+ echo "$src_path:1: no $LICENSE SPDX tag found " >&2
+ RV=1
+ elif [[ $file == *.c ]] || [[ $file == *.cpp ]]; then
+ if ! grep -q -e "\/\/ SPDX-License-Identifier: $LICENSE" $src_path; then
+ echo "$src_path:1: wrong format of $LICENSE SPDX tag" >&2
+ RV=1
+ fi
+ elif [[ $file == *.h ]] || [[ $file == *.hpp ]]; then
+ if ! grep -q -e "\/\* SPDX-License-Identifier: $LICENSE \*\/" $src_path; then
+ echo "$src_path:1: wrong format of $LICENSE SPDX tag" >&2
+ RV=1
+ fi
+ elif [[ $file != LICENSE ]]; then
+ if ! grep -q -e "# SPDX-License-Identifier: $LICENSE" $src_path; then
+ echo "$src_path:1: wrong format of $LICENSE SPDX tag" >&2
+ RV=1
+ fi
+ fi
+
+ if [ $SHALLOW_CLONE -eq 0 ]; then
+ $GIT log --no-merges --format="%ai %aE" -- $file | sort > $TMP
+ else
+ # mark the grafted commits (commits with no parents)
+ $GIT log --no-merges --format="%ai %aE grafted-%p-commit" -- $file | sort > $TMP
+ fi
+
+ # skip checking dates for non-Intel commits
+ [[ ! $(tail -n1 $TMP) =~ "@intel.com" ]] && continue
+
+ # skip checking dates for new files
+ [ $(cat $TMP | wc -l) -le 1 ] && continue
+
+ # grep out the grafted commits (commits with no parents)
+ # and skip checking dates for non-Intel commits
+ grep -v -e "grafted--commit" $TMP | grep -e "@intel.com" > $TMP2
+
+ [ $(cat $TMP2 | wc -l) -eq 0 ] && continue
+
+ FIRST=`head -n1 $TMP2`
+ LAST=` tail -n1 $TMP2`
+
+ YEARS=`sed '
+/Copyright [0-9-]\+.*, Intel Corporation/!d
+s/.*Copyright \([0-9]\+\)-\([0-9]\+\),.*/\1-\2/
+s/.*Copyright \([0-9]\+\),.*/\1-\1/' $src_path`
+ if [ -z "$YEARS" ]; then
+ echo >&2 "$src_path:1: No copyright years found"
+ RV=1
+ continue
+ fi
+
+ HEADER_FIRST=`echo $YEARS | cut -d"-" -f1`
+ HEADER_LAST=` echo $YEARS | cut -d"-" -f2`
+
+ COMMIT_FIRST=`echo $FIRST | cut -d"-" -f1`
+ COMMIT_LAST=` echo $LAST | cut -d"-" -f1`
+ if [ "$COMMIT_FIRST" != "" -a "$COMMIT_LAST" != "" ]; then
+ if [ $HEADER_LAST -lt $COMMIT_LAST ]; then
+ if [ $HEADER_FIRST -lt $COMMIT_FIRST ]; then
+ COMMIT_FIRST=$HEADER_FIRST
+ fi
+ COMMIT_LAST=`date +%G`
+ if [ $COMMIT_FIRST -eq $COMMIT_LAST ]; then
+ NEW=$COMMIT_LAST
+ else
+ NEW=$COMMIT_FIRST-$COMMIT_LAST
+ fi
+ echo "$file:1: error: wrong copyright date: (is: $YEARS, should be: $NEW)" >&2
+ RV=1
+ fi
+ else
+ echo "$file:1: unknown commit dates" >&2
+ RV=1
+ fi
+done
+rm -f $TMP $TMP2 $TEMPFILE
+
+$(dirname "$0")/check-ms-license.pl $FILES
+
+# check if error found
+if [ $RV -eq 0 ]; then
+ echo "Copyright headers are OK."
+else
+ echo "Error(s) in copyright headers found!" >&2
+fi
+exit $RV
diff --git a/src/pmdk/utils/check_license/check-ms-license.pl b/src/pmdk/utils/check_license/check-ms-license.pl
new file mode 100755
index 000000000..fae3c9436
--- /dev/null
+++ b/src/pmdk/utils/check_license/check-ms-license.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl -w
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020, Intel Corporation
+
+use Digest::MD5 "md5_hex";
+
+my $BSD3 = <<EndText;
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * 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.
+
+ * Neither the name of the copyright holder 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 COPYRIGHT
+OWNER 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.
+EndText
+
+# a runaway sed job may alter this file too
+md5_hex($BSD3) eq "066df8826723b6db407a931e5d6084f4"
+ or die "Text of BSD3 license has been corrupted.\n";
+
+my $err = 0;
+
+$BSD3 =~ s/^/ /mg; # indent the text
+$BSD3 =~ s/\n \n/\n\n/sg; # except for empty lines
+
+undef $/;
+for my $f (@ARGV) {
+ next unless -f $f;
+ open F, '<', $f or die "Can't read ï½¢$fï½£\n";
+ $_ = <F>;
+ close F;
+ next unless /Copyright.*(Microsoft Corporation|FUJITSU)/;
+
+ s/^ \*//mg;
+ s/^#//mg;
+ if (index($_, $BSD3) == -1) {
+ $err = 1;
+ print STDERR "Outside copyright but no/wrong license text in $f\n";
+ }
+}
+
+exit $err
diff --git a/src/pmdk/utils/check_license/file-exceptions.sh b/src/pmdk/utils/check_license/file-exceptions.sh
new file mode 100755
index 000000000..a3bdb7425
--- /dev/null
+++ b/src/pmdk/utils/check_license/file-exceptions.sh
@@ -0,0 +1,7 @@
+#!/bin/sh -e
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+# file-exceptions.sh - filter out files not checked for copyright and license
+
+grep -v -E -e '/queue.h$' -e '/getopt.h$' -e '/getopt.c$' -e 'src/core/valgrind/' -e '/testconfig\...$'
diff --git a/src/pmdk/utils/check_sdk_version.py b/src/pmdk/utils/check_sdk_version.py
new file mode 100755
index 000000000..7dc134f01
--- /dev/null
+++ b/src/pmdk/utils/check_sdk_version.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019-2020, Intel Corporation
+
+import argparse
+import os
+from subprocess import check_output, CalledProcessError
+import sys
+import shlex
+from xml.dom import minidom
+from xml.parsers.expat import ExpatError
+
+VALID_SDK_VERSION = '10.0.17134.0'
+
+
+def get_vcxproj_files(root_dir, ignored):
+ """Get a list ".vcxproj" files under PMDK directory."""
+ to_format = []
+ command = 'git ls-files *.vcxproj'
+ try:
+ output = check_output(shlex.split(command),
+ cwd=root_dir).decode("UTF-8")
+ except CalledProcessError as e:
+ sys.exit('Error: "' + command + '" failed with returncode: ' +
+ str(e.returncode))
+
+ for line in output.splitlines():
+ if not line:
+ continue
+ file_path = os.path.join(root_dir, line)
+ if os.path.isfile(file_path):
+ to_format.append(file_path)
+
+ return to_format
+
+
+def get_sdk_version(file):
+ """
+ Get Windows SDK version from modified/new files from the current
+ pull request.
+ """
+ tag = 'WindowsTargetPlatformVersion'
+ try:
+ xml_file = minidom.parse(file)
+ except ExpatError as e:
+ sys.exit('Error: "' + file + '" is incorrect.\n' + str(e))
+ version_list = xml_file.getElementsByTagName(tag)
+ if len(version_list) != 1:
+ sys.exit('Error: the amount of tags "' + tag + '" is other than 1.')
+ version = version_list[0].firstChild.data
+
+ return version
+
+
+def main():
+ parser = argparse.ArgumentParser(prog='check_sdk_version.py',
+ description='The script checks Windows SDK version in .vcxproj files.')
+ parser.add_argument('-d', '--directory',
+ help='Directory of PMDK tree.', required=True)
+ args = parser.parse_args()
+ current_directory = args.directory
+ if not os.path.isdir(current_directory):
+ sys.exit('"' + current_directory + '" is not a directory.')
+
+ files = get_vcxproj_files(current_directory, '')
+ if not files:
+ sys.exit(0)
+ for file in files:
+ sdk_version = get_sdk_version(file)
+ if sdk_version != VALID_SDK_VERSION:
+ sys.exit('Wrong Windows SDK version: ' + sdk_version +
+ ' in file: "' + file + '". Please use: ' + VALID_SDK_VERSION)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/pmdk/utils/check_whitespace b/src/pmdk/utils/check_whitespace
new file mode 100755
index 000000000..083b3e8ff
--- /dev/null
+++ b/src/pmdk/utils/check_whitespace
@@ -0,0 +1,210 @@
+#!/usr/bin/env perl
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2015-2020, Intel Corporation
+
+#
+# check_whitespace -- scrub source tree for whitespace errors
+#
+
+use strict;
+use warnings;
+
+use File::Basename;
+use File::Find;
+use Encode;
+use v5.16;
+
+my $Me = $0;
+$Me =~ s,.*/,,;
+
+$SIG{HUP} = $SIG{INT} = $SIG{TERM} = $SIG{__DIE__} = sub {
+ die @_ if $^S;
+
+ my $errstr = shift;
+
+ die "$Me: ERROR: $errstr";
+};
+
+my $Errcount = 0;
+
+#
+# err -- emit error, keep total error count
+#
+sub err {
+ warn @_, "\n";
+ $Errcount++;
+}
+
+#
+# decode_file_as_string -- slurp an entire file into memory and decode
+#
+sub decode_file_as_string {
+ my ($full, $file) = @_;
+ my $fh;
+ open($fh, '<', $full) or die "$full $!\n";
+
+ local $/;
+ $_ = <$fh>;
+ close $fh;
+
+ # check known encodings or die
+ my $decoded;
+ my @encodings = ("UTF-8", "UTF-16", "UTF-16LE", "UTF-16BE");
+
+ foreach my $enc (@encodings) {
+ eval { $decoded = decode( $enc, $_, Encode::FB_CROAK ) };
+
+ if (!$@) {
+ $decoded =~ s/\R/\n/g;
+ return $decoded;
+ }
+ }
+
+ die "$Me: ERROR: Unknown file encoding";
+}
+
+#
+# check_whitespace -- run the checks on the given file
+#
+sub check_whitespace {
+ my ($full, $file) = @_;
+
+ my $line = 0;
+ my $eol;
+ my $nf = 0;
+ my $fstr = decode_file_as_string($full, $file);
+ my $empty = 0;
+ my $is_python = $full =~ /\.py$/;
+
+ for (split /^/, $fstr) {
+ $line++;
+ if (!$is_python && /^$/) {
+ $empty++;
+ if ($empty > 1) {
+ err("$full:$line: ERROR duplicated empty line");
+ }
+ } else {
+ $empty = 0;
+ }
+
+ $eol = /[\n]/s;
+ if (/^\.nf$/) {
+ err("$full:$line: ERROR: nested .nf") if $nf;
+ $nf = 1;
+ } elsif (/^\.fi$/) {
+ $nf = 0;
+ } elsif ($nf == 0) {
+ chomp;
+ err("$full:$line: ERROR: trailing whitespace") if /\s$/;
+ err("$full:$line: ERROR: spaces before tabs") if / \t/;
+ }
+ }
+
+ err("$full:$line: .nf without .fi") if $nf;
+ err("$full:$line: noeol") unless $eol;
+}
+
+sub check_whitespace_with_exc {
+ my ($full) = @_;
+
+ $_ = $full;
+
+ return 0 if /^[.\/]*src\/common\/queue\.h/;
+ return 0 if /^[.\/]*src\/core\/valgrind\/.*\.h/;
+
+ $_ = basename($full);
+
+ return 0 unless /^(README.*|LICENSE.*|Makefile.*|CMakeLists.txt|.gitignore|TEST.*|RUNTESTS|check_whitespace|.*\.([chp13s]|sh|map|cpp|hpp|inc|PS1|ps1|py|md|cmake))$/;
+ return 0 if -z;
+
+ check_whitespace($full, $_);
+ return 1;
+}
+
+my $verbose = 0;
+my $force = 0;
+my $recursive = 0;
+
+sub check {
+ my ($file) = @_;
+ my $r;
+
+ if ($force) {
+ $r = check_whitespace($file, basename($file));
+ } else {
+ $r = check_whitespace_with_exc($file);
+ }
+
+ if ($verbose) {
+ if ($r == 0) {
+ printf("skipped $file\n");
+ } else {
+ printf("checked $file\n");
+ }
+ }
+}
+
+my @files = ();
+
+foreach my $arg (@ARGV) {
+ if ($arg eq '-v') {
+ $verbose = 1;
+ next;
+ }
+ if ($arg eq '-f') {
+ $force = 1;
+ next;
+ }
+ if ($arg eq '-r') {
+ $recursive = 1;
+ next;
+ }
+ if ($arg eq '-g') {
+ @files = `git ls-tree -r --name-only HEAD`;
+ chomp(@files);
+ next;
+ }
+ if ($arg eq '-h') {
+ printf "Options:
+ -g - check all files tracked by git
+ -r dir - recursively check all files in specified directory
+ -v verbose - print whether file was checked or not
+ -f force - disable blacklist\n";
+ exit 1;
+ }
+
+ if ($recursive == 1) {
+ find(sub {
+ my $full = $File::Find::name;
+
+ if (!$force &&
+ ($full eq './.git' ||
+ $full eq './src/debug' ||
+ $full eq './src/nondebug' ||
+ $full eq './rpmbuild' ||
+ $full eq './dpkgbuild')) {
+ $File::Find::prune = 1;
+ return;
+ }
+
+ return unless -f;
+
+ push @files, $full;
+ }, $arg);
+
+ $recursive = 0;
+ next;
+ }
+
+ push @files, $arg;
+}
+
+if (!@files) {
+ printf "Empty file list!\n";
+}
+
+foreach (@files) {
+ check($_);
+}
+
+exit $Errcount;
diff --git a/src/pmdk/utils/copy-source.sh b/src/pmdk/utils/copy-source.sh
new file mode 100755
index 000000000..5bb2d589d
--- /dev/null
+++ b/src/pmdk/utils/copy-source.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2018, Intel Corporation
+
+#
+# utils/copy-source.sh -- copy source files (from HEAD) to 'path_to_dir/pmdk'
+# directory whether in git repository or not.
+#
+# usage: ./copy-source.sh [path_to_dir] [srcversion]
+
+set -e
+
+DESTDIR="$1"
+SRCVERSION=$2
+
+if [ -d .git ]; then
+ if [ -n "$(git status --porcelain)" ]; then
+ echo "Error: Working directory is dirty: $(git status --porcelain)"
+ exit 1
+ fi
+else
+ echo "Warning: You are not in git repository, working directory might be dirty."
+fi
+
+mkdir -p "$DESTDIR"/pmdk
+echo -n $SRCVERSION > "$DESTDIR"/pmdk/.version
+
+if [ -d .git ]; then
+ git archive HEAD | tar -x -C "$DESTDIR"/pmdk
+else
+ find . \
+ -maxdepth 1 \
+ -not -name $(basename "$DESTDIR") \
+ -not -name . \
+ -exec cp -r "{}" "$DESTDIR"/pmdk \;
+fi
diff --git a/src/pmdk/utils/cstyle b/src/pmdk/utils/cstyle
new file mode 100755
index 000000000..5221a2d56
--- /dev/null
+++ b/src/pmdk/utils/cstyle
@@ -0,0 +1,1037 @@
+#!/usr/bin/env perl
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Portions copyright 2017, Intel Corporation.
+#
+# @(#)cstyle 1.58 98/09/09 (from shannon)
+#ident "%Z%%M% %I% %E% SMI"
+#
+# cstyle - check for some common stylistic errors.
+#
+# cstyle is a sort of "lint" for C coding style.
+# It attempts to check for the style used in the
+# kernel, sometimes known as "Bill Joy Normal Form".
+#
+# There's a lot this can't check for, like proper indentation
+# of code blocks. There's also a lot more this could check for.
+#
+# A note to the non perl literate:
+#
+# perl regular expressions are pretty much like egrep
+# regular expressions, with the following special symbols
+#
+# \s any space character
+# \S any non-space character
+# \w any "word" character [a-zA-Z0-9_]
+# \W any non-word character
+# \d a digit [0-9]
+# \D a non-digit
+# \b word boundary (between \w and \W)
+# \B non-word boundary
+#
+
+require 5.0;
+use IO::File;
+use Getopt::Std;
+use strict;
+use warnings;
+
+my $usage =
+"usage: cstyle [-chpvCP] [-o constructs] file ...
+ -c check continuation indentation inside functions
+ -h perform heuristic checks that are sometimes wrong
+ -p perform some of the more picky checks
+ -v verbose
+ -C don't check anything in header block comments
+ -P check for use of non-POSIX types
+ -o constructs
+ allow a comma-separated list of optional constructs:
+ doxygen allow doxygen-style block comments (/** /*!)
+ splint allow splint-style lint comments (/*@ ... @*/)
+";
+
+my %opts;
+
+if (!getopts("cho:pvCP", \%opts)) {
+ print $usage;
+ exit 2;
+}
+
+my $check_continuation = $opts{'c'};
+my $heuristic = $opts{'h'};
+my $picky = $opts{'p'};
+my $verbose = $opts{'v'};
+my $ignore_hdr_comment = $opts{'C'};
+my $check_posix_types = $opts{'P'};
+
+my $doxygen_comments = 0;
+my $splint_comments = 0;
+
+if (defined($opts{'o'})) {
+ for my $x (split /,/, $opts{'o'}) {
+ if ($x eq "doxygen") {
+ $doxygen_comments = 1;
+ } elsif ($x eq "splint") {
+ $splint_comments = 1;
+ } else {
+ print "cstyle: unrecognized construct \"$x\"\n";
+ print $usage;
+ exit 2;
+ }
+ }
+}
+
+my ($filename, $line, $prev); # shared globals
+
+my $fmt;
+my $hdr_comment_start;
+
+if ($verbose) {
+ $fmt = "%s:%d: %s\n%s\n";
+} else {
+ $fmt = "%s:%d: %s\n";
+}
+
+if ($doxygen_comments) {
+ # doxygen comments look like "/*!" or "/**"; allow them.
+ $hdr_comment_start = qr/^\s*\/\*[\!\*]?$/;
+} else {
+ $hdr_comment_start = qr/^\s*\/\*$/;
+}
+
+# Note, following must be in single quotes so that \s and \w work right.
+my $typename = '(int|char|short|long|unsigned|float|double' .
+ '|\w+_t|struct\s+\w+|union\s+\w+|FILE|BOOL)';
+
+# mapping of old types to POSIX compatible types
+my %old2posix = (
+ 'unchar' => 'uchar_t',
+ 'ushort' => 'ushort_t',
+ 'uint' => 'uint_t',
+ 'ulong' => 'ulong_t',
+ 'u_int' => 'uint_t',
+ 'u_short' => 'ushort_t',
+ 'u_long' => 'ulong_t',
+ 'u_char' => 'uchar_t',
+ 'quad' => 'quad_t'
+);
+
+my $lint_re = qr/\/\*(?:
+ ARGSUSED[0-9]*|NOTREACHED|LINTLIBRARY|VARARGS[0-9]*|
+ CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|
+ FALLTHRU|FALLTHROUGH|LINTED.*?|PRINTFLIKE[0-9]*|
+ PROTOLIB[0-9]*|SCANFLIKE[0-9]*|CSTYLED.*?
+ )\*\//x;
+
+my $splint_re = qr/\/\*@.*?@\*\//x;
+
+my $warlock_re = qr/\/\*\s*(?:
+ VARIABLES\ PROTECTED\ BY|
+ MEMBERS\ PROTECTED\ BY|
+ ALL\ MEMBERS\ PROTECTED\ BY|
+ READ-ONLY\ VARIABLES:|
+ READ-ONLY\ MEMBERS:|
+ VARIABLES\ READABLE\ WITHOUT\ LOCK:|
+ MEMBERS\ READABLE\ WITHOUT\ LOCK:|
+ LOCKS\ COVERED\ BY|
+ LOCK\ UNNEEDED\ BECAUSE|
+ LOCK\ NEEDED:|
+ LOCK\ HELD\ ON\ ENTRY:|
+ READ\ LOCK\ HELD\ ON\ ENTRY:|
+ WRITE\ LOCK\ HELD\ ON\ ENTRY:|
+ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
+ READ\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
+ WRITE\ LOCK\ ACQUIRED\ AS\ SIDE\ EFFECT:|
+ LOCK\ RELEASED\ AS\ SIDE\ EFFECT:|
+ LOCK\ UPGRADED\ AS\ SIDE\ EFFECT:|
+ LOCK\ DOWNGRADED\ AS\ SIDE\ EFFECT:|
+ FUNCTIONS\ CALLED\ THROUGH\ POINTER|
+ FUNCTIONS\ CALLED\ THROUGH\ MEMBER|
+ LOCK\ ORDER:
+ )/x;
+
+my $err_stat = 0; # exit status
+
+if ($#ARGV >= 0) {
+ foreach my $arg (@ARGV) {
+ my $fh = new IO::File $arg, "r";
+ if (!defined($fh)) {
+ printf "%s: can not open\n", $arg;
+ } else {
+ &cstyle($arg, $fh);
+ close $fh;
+ }
+ }
+} else {
+ &cstyle("<stdin>", *STDIN);
+}
+exit $err_stat;
+
+my $no_errs = 0; # set for CSTYLED-protected lines
+
+sub err($) {
+ my ($error) = @_;
+ unless ($no_errs) {
+ if ($verbose) {
+ printf $fmt, $filename, $., $error, $line;
+ } else {
+ printf $fmt, $filename, $., $error;
+ }
+ $err_stat = 1;
+ }
+}
+
+sub err_prefix($$) {
+ my ($prevline, $error) = @_;
+ my $out = $prevline."\n".$line;
+ unless ($no_errs) {
+ printf $fmt, $filename, $., $error, $out;
+ $err_stat = 1;
+ }
+}
+
+sub err_prev($) {
+ my ($error) = @_;
+ unless ($no_errs) {
+ printf $fmt, $filename, $. - 1, $error, $prev;
+ $err_stat = 1;
+ }
+}
+
+sub cstyle($$) {
+
+my ($fn, $filehandle) = @_;
+$filename = $fn; # share it globally
+
+my $in_cpp = 0;
+my $next_in_cpp = 0;
+
+my $in_comment = 0;
+my $in_header_comment = 0;
+my $comment_done = 0;
+my $in_warlock_comment = 0;
+my $in_function = 0;
+my $in_function_header = 0;
+my $in_declaration = 0;
+my $note_level = 0;
+my $nextok = 0;
+my $nocheck = 0;
+
+my $in_string = 0;
+
+my ($okmsg, $comment_prefix);
+
+$line = '';
+$prev = '';
+reset_indent();
+
+line: while (<$filehandle>) {
+ s/\r?\n$//; # strip return and newline
+
+ # save the original line, then remove all text from within
+ # double or single quotes, we do not want to check such text.
+
+ $line = $_;
+
+ #
+ # C allows strings to be continued with a backslash at the end of
+ # the line. We translate that into a quoted string on the previous
+ # line followed by an initial quote on the next line.
+ #
+ # (we assume that no-one will use backslash-continuation with character
+ # constants)
+ #
+ $_ = '"' . $_ if ($in_string && !$nocheck && !$in_comment);
+
+ #
+ # normal strings and characters
+ #
+ s/'([^\\']|\\[^xX0]|\\0[0-9]*|\\[xX][0-9a-fA-F]*)'/''/g;
+ s/"([^\\"]|\\.)*"/\"\"/g;
+
+ #
+ # detect string continuation
+ #
+ if ($nocheck || $in_comment) {
+ $in_string = 0;
+ } else {
+ #
+ # Now that all full strings are replaced with "", we check
+ # for unfinished strings continuing onto the next line.
+ #
+ $in_string =
+ (s/([^"](?:"")*)"([^\\"]|\\.)*\\$/$1""/ ||
+ s/^("")*"([^\\"]|\\.)*\\$/""/);
+ }
+
+ #
+ # figure out if we are in a cpp directive
+ #
+ $in_cpp = $next_in_cpp || /^\s*#/; # continued or started
+ $next_in_cpp = $in_cpp && /\\$/; # only if continued
+
+ # strip off trailing backslashes, which appear in long macros
+ s/\s*\\$//;
+
+ # an /* END CSTYLED */ comment ends a no-check block.
+ if ($nocheck) {
+ if (/\/\* *END *CSTYLED *\*\//) {
+ $nocheck = 0;
+ } else {
+ reset_indent();
+ next line;
+ }
+ }
+
+ # a /*CSTYLED*/ comment indicates that the next line is ok.
+ if ($nextok) {
+ if ($okmsg) {
+ err($okmsg);
+ }
+ $nextok = 0;
+ $okmsg = 0;
+ if (/\/\* *CSTYLED.*\*\//) {
+ /^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
+ $okmsg = $1;
+ $nextok = 1;
+ }
+ $no_errs = 1;
+ } elsif ($no_errs) {
+ $no_errs = 0;
+ }
+
+ # check length of line.
+ # first, a quick check to see if there is any chance of being too long.
+ if (($line =~ tr/\t/\t/) * 7 + length($line) > 80) {
+ # yes, there is a chance.
+ # replace tabs with spaces and check again.
+ my $eline = $line;
+ 1 while $eline =~
+ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
+ if (length($eline) > 80) {
+ # allow long line if it is user visible string
+ # find if line start from " or L" and ends
+ # with " + 2 optional characters
+ # (these characters can be i.e. '");' '" \' or '",' etc...)
+ if($eline =~ /^ *L?".*"[^"]{0,2}$/) {
+ # check if entire line is one string literal
+ $eline =~ s/^ *L?"//;
+ $eline =~ s/"[^"]{0,2}$//;
+
+ if($eline =~ /[^\\]"|[^\\](\\\\)+"/) {
+ err("line > 80 characters");
+ }
+ } else {
+ err("line > 80 characters");
+ }
+ }
+ }
+
+ # ignore NOTE(...) annotations (assumes NOTE is on lines by itself).
+ if ($note_level || /\b_?NOTE\s*\(/) { # if in NOTE or this is NOTE
+ s/[^()]//g; # eliminate all non-parens
+ $note_level += s/\(//g - length; # update paren nest level
+ next;
+ }
+
+ # a /* BEGIN CSTYLED */ comment starts a no-check block.
+ if (/\/\* *BEGIN *CSTYLED *\*\//) {
+ $nocheck = 1;
+ }
+
+ # a /*CSTYLED*/ comment indicates that the next line is ok.
+ if (/\/\* *CSTYLED.*\*\//) {
+ /^.*\/\* *CSTYLED *(.*) *\*\/.*$/;
+ $okmsg = $1;
+ $nextok = 1;
+ }
+ if (/\/\/ *CSTYLED/) {
+ /^.*\/\/ *CSTYLED *(.*)$/;
+ $okmsg = $1;
+ $nextok = 1;
+ }
+
+ # universal checks; apply to everything
+ if (/\t +\t/) {
+ err("spaces between tabs");
+ }
+ if (/ \t+ /) {
+ err("tabs between spaces");
+ }
+ if (/\s$/) {
+ err("space or tab at end of line");
+ }
+ if (/[^ \t(]\/\*/ && !/\w\(\/\*.*\*\/\);/) {
+ err("comment preceded by non-blank");
+ }
+
+ # is this the beginning or ending of a function?
+ # (not if "struct foo\n{\n")
+ if (/^{$/ && $prev =~ /\)\s*(const\s*)?(\/\*.*\*\/\s*)?\\?$/) {
+ $in_function = 1;
+ $in_declaration = 1;
+ $in_function_header = 0;
+ $prev = $line;
+ next line;
+ }
+ if (/^}\s*(\/\*.*\*\/\s*)*$/) {
+ if ($prev =~ /^\s*return\s*;/) {
+ err_prev("unneeded return at end of function");
+ }
+ $in_function = 0;
+ reset_indent(); # we don't check between functions
+ $prev = $line;
+ next line;
+ }
+ if (/^\w*\($/) {
+ $in_function_header = 1;
+ }
+
+ if ($in_warlock_comment && /\*\//) {
+ $in_warlock_comment = 0;
+ $prev = $line;
+ next line;
+ }
+
+ # a blank line terminates the declarations within a function.
+ # XXX - but still a problem in sub-blocks.
+ if ($in_declaration && /^$/) {
+ $in_declaration = 0;
+ }
+
+ if ($comment_done) {
+ $in_comment = 0;
+ $in_header_comment = 0;
+ $comment_done = 0;
+ }
+ # does this looks like the start of a block comment?
+ if (/$hdr_comment_start/) {
+ if (!/^\t*\/\*/) {
+ err("block comment not indented by tabs");
+ }
+ $in_comment = 1;
+ /^(\s*)\//;
+ $comment_prefix = $1;
+ if ($comment_prefix eq "") {
+ $in_header_comment = 1;
+ }
+ $prev = $line;
+ next line;
+ }
+ # are we still in the block comment?
+ if ($in_comment) {
+ if (/^$comment_prefix \*\/$/) {
+ $comment_done = 1;
+ } elsif (/\*\//) {
+ $comment_done = 1;
+ err("improper block comment close")
+ unless ($ignore_hdr_comment && $in_header_comment);
+ } elsif (!/^$comment_prefix \*[ \t]/ &&
+ !/^$comment_prefix \*$/) {
+ err("improper block comment")
+ unless ($ignore_hdr_comment && $in_header_comment);
+ }
+ }
+
+ if ($in_header_comment && $ignore_hdr_comment) {
+ $prev = $line;
+ next line;
+ }
+
+ # check for errors that might occur in comments and in code.
+
+ # allow spaces to be used to draw pictures in header and block comments.
+ if (/[^ ] / && !/".* .*"/ && !$in_header_comment && !$in_comment) {
+ err("spaces instead of tabs");
+ }
+ if (/^ / && !/^ \*[ \t\/]/ && !/^ \*$/ &&
+ (!/^ \w/ || $in_function != 0)) {
+ err("indent by spaces instead of tabs");
+ }
+ if (/^\t+ [^ \t\*]/ || /^\t+ \S/ || /^\t+ \S/) {
+ err("continuation line not indented by 4 spaces");
+ }
+ if (/$warlock_re/ && !/\*\//) {
+ $in_warlock_comment = 1;
+ $prev = $line;
+ next line;
+ }
+ if (/^\s*\/\*./ && !/^\s*\/\*.*\*\// && !/$hdr_comment_start/) {
+ err("improper first line of block comment");
+ }
+
+ if ($in_comment) { # still in comment, don't do further checks
+ $prev = $line;
+ next line;
+ }
+
+ if ((/[^(]\/\*\S/ || /^\/\*\S/) &&
+ !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
+ err("missing blank after open comment");
+ }
+ if (/\S\*\/[^)]|\S\*\/$/ &&
+ !(/$lint_re/ || ($splint_comments && /$splint_re/))) {
+ err("missing blank before close comment");
+ }
+ if (/\/\/\S/) { # C++ comments
+ err("missing blank after start comment");
+ }
+ # check for unterminated single line comments, but allow them when
+ # they are used to comment out the argument list of a function
+ # declaration.
+ if (/\S.*\/\*/ && !/\S.*\/\*.*\*\// && !/\(\/\*/) {
+ err("unterminated single line comment");
+ }
+
+ if (/^(#else|#endif|#include)(.*)$/) {
+ $prev = $line;
+ if ($picky) {
+ my $directive = $1;
+ my $clause = $2;
+ # Enforce ANSI rules for #else and #endif: no noncomment
+ # identifiers are allowed after #endif or #else. Allow
+ # C++ comments since they seem to be a fact of life.
+ if ((($1 eq "#endif") || ($1 eq "#else")) &&
+ ($clause ne "") &&
+ (!($clause =~ /^\s+\/\*.*\*\/$/)) &&
+ (!($clause =~ /^\s+\/\/.*$/))) {
+ err("non-comment text following " .
+ "$directive (or malformed $directive " .
+ "directive)");
+ }
+ }
+ next line;
+ }
+
+ #
+ # delete any comments and check everything else. Note that
+ # ".*?" is a non-greedy match, so that we don't get confused by
+ # multiple comments on the same line.
+ #
+ s/\/\*.*?\*\//\x01/g;
+ s/\/\/.*$/\x01/; # C++ comments
+
+ # delete any trailing whitespace; we have already checked for that.
+ s/\s*$//;
+
+ # following checks do not apply to text in comments.
+
+ if (/[^ \t\+]\+[^\+=]/ || /[^\+]\+[^ \+=]/) {
+ err("missing space around + operator");
+ }
+ if (/[^ \t]\+=/ || /\+=[^ ]/) {
+ err("missing space around += operator");
+ }
+ if (/[^ \t\-]\-[^\->]/ && !/\(\w+\)\-\w/ && !/[\(\[]\-[\w \t]+[\)\],]/) {
+ err("missing space before - operator");
+ }
+ if (/[^\-]\-[^ \-=>]/ && !/\(\-\w+\)/ &&
+ !/(return|case|=|>|<|\?|:|,|^[ \t]+)[ \t]+\-[\w\(]/ && !/(\([^\)]+\)|\[|\()\-[\w\(\]]/) {
+ err("missing space after - operator");
+ }
+ if (/(return|case|=|\?|:|,|\[)[ \t]+\-[ \t]/ || /[\(\[]\-[ \t]/) {
+ err("extra space after - operator");
+ }
+ if (/[ \t]\+\+ /) {
+ err("extra space before or after ++ operator");
+ }
+ if (/[ \t]\-\- /) {
+ err("extra space before or after -- operator");
+ }
+ if (/[^ \t]\-=/ || /\-=[^ ]/) {
+ err("missing space around -= operator");
+ }
+ if (/[^ \t][\%\/]/ || /[\%\/][^ =]/ || /[\%\/]=[^ ]/) {
+ err("missing space around one of operators: % %= / /=");
+ }
+ if (/[^ \t]\*=/ || /\*=[^ ]/) {
+ err("missing space around *= operator");
+ }
+ if (/[^ \t\(\)\*\[]\*/) {
+ err("missing space before * operator");
+ }
+ if (/\*[^ =\*\w\(,]/ && !/\(.+ \*+\)/ && !/\*\[\]/ &&
+ !/\*\-\-\w/ && !/\*\+\+\w/ && !/\*\)/) {
+ err("missing space after * operator");
+ }
+ if (/[^<>\s][!<>=]=/ || /[^<>][!<>=]=[^\s,]/ ||
+ (/[^->]>[^,=>\s]/ && !/[^->]>$/) ||
+ (/[^<]<[^,=<\s]/ && !/[^<]<$/) ||
+ /[^<\s]<[^<]/ || /[^->\s]>[^>]/) {
+ err("missing space around relational operator");
+ }
+ if (/\S>>=/ || /\S<<=/ || />>=\S/ || /<<=\S/ || /\S[-+*\/&|^%]=/ ||
+ (/[^-+*\/&|^%!<>=\s]=[^=]/ && !/[^-+*\/&|^%!<>=\s]=$/) ||
+ (/[^!<>=]=[^=\s]/ && !/[^!<>=]=$/)) {
+ # XXX - should only check this for C++ code
+ # XXX - there are probably other forms that should be allowed
+ if (!/\soperator=/) {
+ err("missing space around assignment operator");
+ }
+ }
+ if (/[,;]\S/ && !/\bfor \(;;\)/) {
+ err("comma or semicolon followed by non-blank");
+ }
+ # allow "for" statements to have empty "while" clauses
+ if (/\s[,;]/ && !/^[\t]+;$/ && !/^\s*for \([^;]*; ;[^;]*\)/) {
+ err("comma or semicolon preceded by blank");
+ }
+ if (/^\s*(&&|\|\|)/) {
+ err("improper boolean continuation");
+ }
+ if (/\S *(&&|\|\|)/ || /(&&|\|\|) *\S/) {
+ err("more than one space around boolean operator");
+ }
+ if (/\b(for|if|while|switch|return|case)\(/) {
+ err("missing space between keyword and paren");
+ }
+ if (/(\b(for|if|while|switch|return)\b.*){2,}/ && !/^#define/) {
+ # multiple "case" and "sizeof" allowed
+ err("more than one keyword on line");
+ }
+ if (/\b(for|if|while|switch|return|case)\s\s+\(/ &&
+ !/^#if\s+\(/) {
+ err("extra space between keyword and paren");
+ }
+ # try to detect "func (x)" but not "if (x)" or
+ # "#define foo (x)" or "int (*func)();"
+ if (/\w\s\(/) {
+ my $s = $_;
+ # strip off all keywords on the line
+ s/\b(for|if|while|switch|return|case)\s\(/XXX(/g;
+ s/\b(sizeof|typeof|__typeof__)\s*\(/XXX(/g;
+ s/#elif\s\(/XXX(/g;
+ s/^#define\s+\w+\s+\(/XXX(/;
+ # do not match things like "void (*f)();"
+ # or "typedef void (func_t)();"
+ s/\w\s\(+\*/XXX(*/g;
+ s/\b($typename|void)\s+\(+/XXX(/og;
+ s/\btypedef\s($typename|void)\s+\(+/XXX(/og;
+ # do not match "__attribute__ ((format (...)))"
+ s/\b__attribute__\s*\(\(format\s*\(/__attribute__((XXX(/g;
+ if (/\w\s\(/) {
+ err("extra space between function name and left paren");
+ }
+ $_ = $s;
+ }
+ # try to detect "int foo(x)", but not "extern int foo(x);"
+ # XXX - this still trips over too many legitimate things,
+ # like "int foo(x,\n\ty);"
+# if (/^(\w+(\s|\*)+)+\w+\(/ && !/\)[;,](\s|\x01)*$/ &&
+# !/^(extern|static)\b/) {
+# err("return type of function not on separate line");
+# }
+ # this is a close approximation
+ if (/^(\w+(\s|\*)+)+\w+\(.*\)(\s|\x01)*$/ &&
+ !/^(extern|static)\b/) {
+ err("return type of function not on separate line");
+ }
+ if (/^#define\t/ || /^#ifdef\t/ || /^#ifndef\t/) {
+ err("#define/ifdef/ifndef followed by tab instead of space");
+ }
+ if (/^#define\s\s+/ || /^#ifdef\s\s+/ || /^#ifndef\s\s+/) {
+ err("#define/ifdef/ifndef followed by more than one space");
+ }
+ # AON C-style doesn't require this.
+ #if (/^\s*return\W[^;]*;/ && !/^\s*return\s*\(.*\);/) {
+ # err("unparenthesized return expression");
+ #}
+ if (/\bsizeof\b/ && !/\bsizeof\s*\(.*\)/) {
+ err("unparenthesized sizeof expression");
+ }
+ if (/\b(sizeof|typeof)\b/ && /\b(sizeof|typeof)\s+\(.*\)/) {
+ err("spaces between sizeof/typeof expression and paren");
+ }
+ if (/\(\s/) {
+ err("whitespace after left paren");
+ }
+ # allow "for" statements to have empty "continue" clauses
+ if (/\s\)/ && !/^\s*for \([^;]*;[^;]*; \)/) {
+ err("whitespace before right paren");
+ }
+ if (/^\s*\(void\)[^ ]/) {
+ err("missing space after (void) cast");
+ }
+ if (/\S\{/ && !/\{\{/ && !/\(struct \w+\)\{/) {
+ err("missing space before left brace");
+ }
+ if ($in_function && /^\s+{/ &&
+ ($prev =~ /\)\s*$/ || $prev =~ /\bstruct\s+\w+$/)) {
+ err("left brace starting a line");
+ }
+ if (/}(else|while)/) {
+ err("missing space after right brace");
+ }
+ if (/}\s\s+(else|while)/) {
+ err("extra space after right brace");
+ }
+ if (/\b_VOID\b|\bVOID\b|\bSTATIC\b/) {
+ err("obsolete use of VOID or STATIC");
+ }
+ if (/\b($typename|void)\*/o) {
+ err("missing space between type name and *");
+ }
+ if (/^\s+#/) {
+ err("preprocessor statement not in column 1");
+ }
+ if (/^#\s/) {
+ err("blank after preprocessor #");
+ }
+ if (/!\s*(strcmp|strncmp|bcmp)\s*\(/) {
+ err("don't use boolean ! with comparison functions");
+ }
+ if (/^\S+\([\S\s]*\)\s*{/) {
+ err("brace of function definition not at beginning of line");
+ }
+ if (/static\s+\S+\s*=\s*(0|NULL)\s*;/) {
+ err("static variable initialized with 0 or NULL");
+ }
+ if (/typedef[\S\s]+\*\s*\w+\s*;/) {
+ err("typedefed pointer type");
+ }
+ if (/unsigned\s+int\s/) {
+ err("'unsigned int' instead of just 'unsigned'");
+ }
+ if (/long\s+long\s+int\s/) {
+ err("'long long int' instead of just 'long long'");
+ } elsif (/long\s+int\s/) {
+ err("'long int' instead of just 'long'");
+ }
+
+ #
+ # We completely ignore, for purposes of indentation:
+ # * lines outside of functions
+ # * preprocessor lines
+ #
+ if ($check_continuation && $in_function && !$in_cpp) {
+ process_indent($_);
+ }
+ if ($picky) {
+ # try to detect spaces after casts, but allow (e.g.)
+ # "sizeof (int) + 1", "void (*funcptr)(int) = foo;", and
+ # "int foo(int) __NORETURN;"
+ if ((/^\($typename( \*+)?\)\s/o ||
+ /\W\($typename( \*+)?\)\s/o) &&
+ !/sizeof\($typename( \*)?\)\s/o &&
+ !/\($typename( \*+)?\)\s+=[^=]/o) {
+ err("space after cast");
+ }
+ if (/\b($typename|void)\s*\*\s/o &&
+ !/\b($typename|void)\s*\*\s+const\b/o) {
+ err("unary * followed by space");
+ }
+ }
+ if ($check_posix_types) {
+ # try to detect old non-POSIX types.
+ # POSIX requires all non-standard typedefs to end in _t,
+ # but historically these have been used.
+ if (/\b(unchar|ushort|uint|ulong|u_int|u_short|u_long|u_char|quad)\b/) {
+ err("non-POSIX typedef $1 used: use $old2posix{$1} instead");
+ }
+ }
+ if ($heuristic) {
+ # cannot check this everywhere due to "struct {\n...\n} foo;"
+ if ($in_function && !$in_declaration &&
+ /}./ && !/}\s+=/ && !/{.*}[;,]$/ && !/}(\s|\x01)*$/ &&
+ !/} (else|while)/ && !/}}/) {
+ err("possible bad text following right brace");
+ }
+ # cannot check this because sub-blocks in
+ # the middle of code are ok
+ if ($in_function && /^\s+{/) {
+ err("possible left brace starting a line");
+ }
+ }
+ if (/^\s*else\W/) {
+ if ($prev =~ /^\s*}$/) {
+ err_prefix($prev,
+ "else and right brace should be on same line");
+ }
+ }
+ $prev = $line;
+}
+
+if ($prev eq "") {
+ err("last line in file is blank");
+}
+
+}
+
+#
+# Continuation-line checking
+#
+# The rest of this file contains the code for the continuation checking
+# engine. It's a pretty simple state machine which tracks the expression
+# depth (unmatched '('s and '['s).
+#
+# Keep in mind that the argument to process_indent() has already been heavily
+# processed; all comments have been replaced by control-A, and the contents of
+# strings and character constants have been elided.
+#
+
+my $cont_in; # currently inside of a continuation
+my $cont_off; # skipping an initializer or definition
+my $cont_noerr; # suppress cascading errors
+my $cont_start; # the line being continued
+my $cont_base; # the base indentation
+my $cont_first; # this is the first line of a statement
+my $cont_multiseg; # this continuation has multiple segments
+
+my $cont_special; # this is a C statement (if, for, etc.)
+my $cont_macro; # this is a macro
+my $cont_case; # this is a multi-line case
+
+my @cont_paren; # the stack of unmatched ( and [s we've seen
+
+sub
+reset_indent()
+{
+ $cont_in = 0;
+ $cont_off = 0;
+}
+
+sub
+delabel($)
+{
+ #
+ # replace labels with tabs. Note that there may be multiple
+ # labels on a line.
+ #
+ local $_ = $_[0];
+
+ while (/^(\t*)( *(?:(?:\w+\s*)|(?:case\b[^:]*)): *)(.*)$/) {
+ my ($pre_tabs, $label, $rest) = ($1, $2, $3);
+ $_ = $pre_tabs;
+ while ($label =~ s/^([^\t]*)(\t+)//) {
+ $_ .= "\t" x (length($2) + length($1) / 8);
+ }
+ $_ .= ("\t" x (length($label) / 8)).$rest;
+ }
+
+ return ($_);
+}
+
+sub
+process_indent($)
+{
+ require strict;
+ local $_ = $_[0]; # preserve the global $_
+
+ s/\x01//g; # No comments
+ s/\s+$//; # Strip trailing whitespace
+
+ return if (/^$/); # skip empty lines
+
+ # regexps used below; keywords taking (), macros, and continued cases
+ my $special = '(?:(?:\}\s*)?else\s+)?(?:if|for|while|switch)\b';
+ my $macro = '[A-Z_][A-Z_0-9]*\(';
+ my $case = 'case\b[^:]*$';
+
+ # skip over enumerations, array definitions, initializers, etc.
+ if ($cont_off <= 0 && !/^\s*$special/ &&
+ (/(?:(?:\b(?:enum|struct|union)\s*[^\{]*)|(?:\s+=\s*))\{/ ||
+ (/^\s*{/ && $prev =~ /=\s*(?:\/\*.*\*\/\s*)*$/))) {
+ $cont_in = 0;
+ $cont_off = tr/{/{/ - tr/}/}/;
+ return;
+ }
+ if ($cont_off) {
+ $cont_off += tr/{/{/ - tr/}/}/;
+ return;
+ }
+
+ if (!$cont_in) {
+ $cont_start = $line;
+
+ if (/^\t* /) {
+ err("non-continuation indented 4 spaces");
+ $cont_noerr = 1; # stop reporting
+ }
+ $_ = delabel($_); # replace labels with tabs
+
+ # check if the statement is complete
+ return if (/^\s*\}?$/);
+ return if (/^\s*\}?\s*else\s*\{?$/);
+ return if (/^\s*do\s*\{?$/);
+ return if (/{$/);
+ return if (/}[,;]?$/);
+
+ # Allow macros on their own lines
+ return if (/^\s*[A-Z_][A-Z_0-9]*$/);
+
+ # cases we don't deal with, generally non-kosher
+ if (/{/) {
+ err("stuff after {");
+ return;
+ }
+
+ # Get the base line, and set up the state machine
+ /^(\t*)/;
+ $cont_base = $1;
+ $cont_in = 1;
+ @cont_paren = ();
+ $cont_first = 1;
+ $cont_multiseg = 0;
+
+ # certain things need special processing
+ $cont_special = /^\s*$special/? 1 : 0;
+ $cont_macro = /^\s*$macro/? 1 : 0;
+ $cont_case = /^\s*$case/? 1 : 0;
+ } else {
+ $cont_first = 0;
+
+ # Strings may be pulled back to an earlier (half-)tabstop
+ unless ($cont_noerr || /^$cont_base / ||
+ (/^\t*(?: )?(?:gettext\()?\"/ && !/^$cont_base\t/)) {
+ err_prefix($cont_start,
+ "continuation should be indented 4 spaces");
+ }
+ }
+
+ my $rest = $_; # keeps the remainder of the line
+
+ #
+ # The split matches 0 characters, so that each 'special' character
+ # is processed separately. Parens and brackets are pushed and
+ # popped off the @cont_paren stack. For normal processing, we wait
+ # until a ; or { terminates the statement. "special" processing
+ # (if/for/while/switch) is allowed to stop when the stack empties,
+ # as is macro processing. Case statements are terminated with a :
+ # and an empty paren stack.
+ #
+ foreach $_ (split /[^\(\)\[\]\{\}\;\:]*/) {
+ next if (length($_) == 0);
+
+ # rest contains the remainder of the line
+ my $rxp = "[^\Q$_\E]*\Q$_\E";
+ $rest =~ s/^$rxp//;
+
+ if (/\(/ || /\[/) {
+ push @cont_paren, $_;
+ } elsif (/\)/ || /\]/) {
+ my $cur = $_;
+ tr/\)\]/\(\[/;
+
+ my $old = (pop @cont_paren);
+ if (!defined($old)) {
+ err("unexpected '$cur'");
+ $cont_in = 0;
+ last;
+ } elsif ($old ne $_) {
+ err("'$cur' mismatched with '$old'");
+ $cont_in = 0;
+ last;
+ }
+
+ #
+ # If the stack is now empty, do special processing
+ # for if/for/while/switch and macro statements.
+ #
+ next if (@cont_paren != 0);
+ if ($cont_special) {
+ if ($rest =~ /^\s*{?$/) {
+ $cont_in = 0;
+ last;
+ }
+ if ($rest =~ /^\s*;$/) {
+ err("empty if/for/while body ".
+ "not on its own line");
+ $cont_in = 0;
+ last;
+ }
+ if (!$cont_first && $cont_multiseg == 1) {
+ err_prefix($cont_start,
+ "multiple statements continued ".
+ "over multiple lines");
+ $cont_multiseg = 2;
+ } elsif ($cont_multiseg == 0) {
+ $cont_multiseg = 1;
+ }
+ # We've finished this section, start
+ # processing the next.
+ goto section_ended;
+ }
+ if ($cont_macro) {
+ if ($rest =~ /^$/) {
+ $cont_in = 0;
+ last;
+ }
+ }
+ } elsif (/\;/) {
+ if ($cont_case) {
+ err("unexpected ;");
+ } elsif (!$cont_special) {
+ err("unexpected ;") if (@cont_paren != 0);
+ if (!$cont_first && $cont_multiseg == 1) {
+ err_prefix($cont_start,
+ "multiple statements continued ".
+ "over multiple lines");
+ $cont_multiseg = 2;
+ } elsif ($cont_multiseg == 0) {
+ $cont_multiseg = 1;
+ }
+ if ($rest =~ /^$/) {
+ $cont_in = 0;
+ last;
+ }
+ if ($rest =~ /^\s*special/) {
+ err("if/for/while/switch not started ".
+ "on its own line");
+ }
+ goto section_ended;
+ }
+ } elsif (/\{/) {
+ err("{ while in parens/brackets") if (@cont_paren != 0);
+ err("stuff after {") if ($rest =~ /[^\s}]/);
+ $cont_in = 0;
+ last;
+ } elsif (/\}/) {
+ err("} while in parens/brackets") if (@cont_paren != 0);
+ if (!$cont_special && $rest !~ /^\s*(while|else)\b/) {
+ if ($rest =~ /^$/) {
+ err("unexpected }");
+ } else {
+ err("stuff after }");
+ }
+ $cont_in = 0;
+ last;
+ }
+ } elsif (/\:/ && $cont_case && @cont_paren == 0) {
+ err("stuff after multi-line case") if ($rest !~ /$^/);
+ $cont_in = 0;
+ last;
+ }
+ next;
+section_ended:
+ # End of a statement or if/while/for loop. Reset
+ # cont_special and cont_macro based on the rest of the
+ # line.
+ $cont_special = ($rest =~ /^\s*$special/)? 1 : 0;
+ $cont_macro = ($rest =~ /^\s*$macro/)? 1 : 0;
+ $cont_case = 0;
+ next;
+ }
+ $cont_noerr = 0 if (!$cont_in);
+}
diff --git a/src/pmdk/utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch b/src/pmdk/utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch
new file mode 100644
index 000000000..9738942aa
--- /dev/null
+++ b/src/pmdk/utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch
@@ -0,0 +1,27 @@
+From b5179dc4822eaab192361da05aa95d98f523960f Mon Sep 17 00:00:00 2001
+From: Lukasz Dorau <lukasz.dorau@intel.com>
+Date: Mon, 7 May 2018 12:05:40 +0200
+Subject: [PATCH] travis: fix travisci_build_coverity_scan.sh
+
+---
+ travisci_build_coverity_scan.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/travisci_build_coverity_scan.sh b/travisci_build_coverity_scan.sh
+index ad9d4afcf..562b08bcc 100644
+--- a/travisci_build_coverity_scan.sh
++++ b/travisci_build_coverity_scan.sh
+@@ -92,8 +92,8 @@ response=$(curl \
+ --form description="Travis CI build" \
+ $UPLOAD_URL)
+ status_code=$(echo "$response" | sed -n '$p')
+-if [ "$status_code" != "201" ]; then
++if [ "$status_code" != "200" ]; then
+ TEXT=$(echo "$response" | sed '$d')
+- echo -e "\033[33;1mCoverity Scan upload failed: $TEXT.\033[0m"
++ echo -e "\033[33;1mCoverity Scan upload failed: $response.\033[0m"
+ exit 1
+ fi
+--
+2.13.6
+
diff --git a/src/pmdk/utils/docker/README b/src/pmdk/utils/docker/README
new file mode 100644
index 000000000..b4a271359
--- /dev/null
+++ b/src/pmdk/utils/docker/README
@@ -0,0 +1,19 @@
+Persistent Memory Development Kit
+
+This is utils/docker/README.
+
+Scripts in this directory let Travis CI run a Docker container with ubuntu-
+or fedora-based environment and build PMDK project inside it.
+
+'build-local.sh' can be used to build PMDK locally.
+
+'build-CI.sh' is used for building PMDK on Travis and GitHub Actions CIs
+
+NOTE:
+If you commit changes to any Dockerfile or shell script in the 'images'
+subdirectory and then do git-rebase before pushing your commits to the
+repository, make sure that you do not squash the commit which is the head in
+your repository. This will let Travis and GitHub Actions CIs recreate
+Docker images used during the build before the build. Otherwise the not-updated
+Docker image will be pulled from the Docker Hub and used during the build on
+Travis and GitHub Actions CIs.
diff --git a/src/pmdk/utils/docker/build-CI.sh b/src/pmdk/utils/docker/build-CI.sh
new file mode 100755
index 000000000..1b75d3b94
--- /dev/null
+++ b/src/pmdk/utils/docker/build-CI.sh
@@ -0,0 +1,143 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# build-CI.sh - runs a Docker container from a Docker image with environment
+# prepared for building PMDK project and starts building PMDK.
+#
+# This script is used for building PMDK on Travis and GitHub Actions CIs.
+#
+
+set -e
+
+source $(dirname $0)/set-ci-vars.sh
+source $(dirname $0)/set-vars.sh
+source $(dirname $0)/valid-branches.sh
+
+if [[ "$CI_EVENT_TYPE" != "cron" && "$CI_BRANCH" != "coverity_scan" \
+ && "$COVERITY" -eq 1 ]]; then
+ echo "INFO: Skip Coverity scan job if build is triggered neither by " \
+ "'cron' nor by a push to 'coverity_scan' branch"
+ exit 0
+fi
+
+if [[ ( "$CI_EVENT_TYPE" == "cron" || "$CI_BRANCH" == "coverity_scan" )\
+ && "$COVERITY" -ne 1 ]]; then
+ echo "INFO: Skip regular jobs if build is triggered either by 'cron'" \
+ " or by a push to 'coverity_scan' branch"
+ exit 0
+fi
+
+if [[ -z "$OS" || -z "$OS_VER" ]]; then
+ echo "ERROR: The variables OS and OS_VER have to be set properly " \
+ "(eg. OS=ubuntu, OS_VER=16.04)."
+ exit 1
+fi
+
+if [[ -z "$HOST_WORKDIR" ]]; then
+ echo "ERROR: The variable HOST_WORKDIR has to contain a path to " \
+ "the root of the PMDK project on the host machine"
+ exit 1
+fi
+
+if [[ -z "$TEST_BUILD" ]]; then
+ TEST_BUILD=all
+fi
+
+imageName=${DOCKERHUB_REPO}:1.10-${OS}-${OS_VER}-${CI_CPU_ARCH}
+containerName=pmdk-${OS}-${OS_VER}
+
+if [[ $MAKE_PKG -eq 0 ]] ; then command="./run-build.sh"; fi
+if [[ $MAKE_PKG -eq 1 ]] ; then command="./run-build-package.sh"; fi
+if [[ $COVERAGE -eq 1 ]] ; then command="./run-coverage.sh"; ci_env=`bash <(curl -s https://codecov.io/env)`; fi
+
+if [[ ( "$CI_EVENT_TYPE" == "cron" || "$CI_BRANCH" == "coverity_scan" )\
+ && "$COVERITY" -eq 1 ]]; then
+ command="./run-coverity.sh"
+fi
+
+if [ -n "$DNS_SERVER" ]; then DNS_SETTING=" --dns=$DNS_SERVER "; fi
+if [[ -f $CI_FILE_SKIP_BUILD_PKG_CHECK ]]; then BUILD_PACKAGE_CHECK=n; else BUILD_PACKAGE_CHECK=y; fi
+if [ -z "$NDCTL_ENABLE" ]; then ndctl_enable=; else ndctl_enable="--env NDCTL_ENABLE=$NDCTL_ENABLE"; fi
+if [[ $UBSAN -eq 1 ]]; then for x in C CPP LD; do declare EXTRA_${x}FLAGS=-fsanitize=undefined; done; fi
+
+# Only run doc update on $GITHUB_REPO master or stable branch
+if [[ -z "${CI_BRANCH}" || -z "${TARGET_BRANCHES[${CI_BRANCH}]}" || "$CI_EVENT_TYPE" == "pull_request" || "$CI_REPO_SLUG" != "${GITHUB_REPO}" ]]; then
+ AUTO_DOC_UPDATE=0
+fi
+
+# Check if we are running on a CI (Travis or GitHub Actions)
+[ -n "$GITHUB_ACTIONS" -o -n "$TRAVIS" ] && CI_RUN="YES" || CI_RUN="NO"
+
+# We have a blacklist only for ppc64le arch
+if [[ "$CI_CPU_ARCH" == ppc64le ]] ; then BLACKLIST_FILE=../../utils/docker/ppc64le.blacklist; fi
+
+# docker on travis + ppc64le runs inside an LXD container and for security
+# limits what can be done inside it, and as such, `docker run` fails with
+# > the input device is not a TTY
+# when using -t because of limited permissions to /dev imposed by LXD.
+if [[ -n "$TRAVIS" && "$CI_CPU_ARCH" == ppc64le ]] || [[ -n "$GITHUB_ACTIONS" ]]; then
+ TTY=''
+else
+ TTY='-t'
+fi
+
+WORKDIR=/pmdk
+SCRIPTSDIR=$WORKDIR/utils/docker
+
+# Run a container with
+# - environment variables set (--env)
+# - host directory containing PMDK source mounted (-v)
+# - a tmpfs /tmp with the necessary size and permissions (--tmpfs)*
+# - working directory set (-w)
+#
+# * We need a tmpfs /tmp inside docker but we cannot run it with --privileged
+# and do it from inside, so we do using this docker-run option.
+# By default --tmpfs add nosuid,nodev,noexec to the mount flags, we don't
+# want that and just to make sure we add the usually default rw,relatime just
+# in case docker change the defaults.
+docker run --rm --name=$containerName -i $TTY \
+ $DNS_SETTING \
+ $ci_env \
+ --env http_proxy=$http_proxy \
+ --env https_proxy=$https_proxy \
+ --env AUTO_DOC_UPDATE=$AUTO_DOC_UPDATE \
+ --env CC=$PMDK_CC \
+ --env CXX=$PMDK_CXX \
+ --env VALGRIND=$VALGRIND \
+ --env EXTRA_CFLAGS=$EXTRA_CFLAGS \
+ --env EXTRA_CXXFLAGS=$EXTRA_CXXFLAGS \
+ --env EXTRA_LDFLAGS=$EXTRA_LDFLAGS \
+ --env REMOTE_TESTS=$REMOTE_TESTS \
+ --env TEST_BUILD=$TEST_BUILD \
+ --env WORKDIR=$WORKDIR \
+ --env EXPERIMENTAL=$EXPERIMENTAL \
+ --env BUILD_PACKAGE_CHECK=$BUILD_PACKAGE_CHECK \
+ --env SCRIPTSDIR=$SCRIPTSDIR \
+ --env TRAVIS=$TRAVIS \
+ --env CI_COMMIT_RANGE=$CI_COMMIT_RANGE \
+ --env CI_COMMIT=$CI_COMMIT \
+ --env CI_REPO_SLUG=$CI_REPO_SLUG \
+ --env CI_BRANCH=$CI_BRANCH \
+ --env CI_EVENT_TYPE=$CI_EVENT_TYPE \
+ --env DOC_UPDATE_GITHUB_TOKEN=$DOC_UPDATE_GITHUB_TOKEN \
+ --env COVERITY_SCAN_TOKEN=$COVERITY_SCAN_TOKEN \
+ --env COVERITY_SCAN_NOTIFICATION_EMAIL=$COVERITY_SCAN_NOTIFICATION_EMAIL \
+ --env FAULT_INJECTION=$FAULT_INJECTION \
+ --env GITHUB_ACTIONS=$GITHUB_ACTIONS \
+ --env GITHUB_HEAD_REF=$GITHUB_HEAD_REF \
+ --env GITHUB_REPO=$GITHUB_REPO \
+ --env GITHUB_REPOSITORY=$GITHUB_REPOSITORY \
+ --env GITHUB_REF=$GITHUB_REF \
+ --env GITHUB_RUN_ID=$GITHUB_RUN_ID \
+ --env GITHUB_SHA=$GITHUB_SHA \
+ --env CI_RUN=$CI_RUN \
+ --env SRC_CHECKERS=$SRC_CHECKERS \
+ --env BLACKLIST_FILE=$BLACKLIST_FILE \
+ $ndctl_enable \
+ --tmpfs /tmp:rw,relatime,suid,dev,exec,size=6G \
+ -v $HOST_WORKDIR:$WORKDIR \
+ -v /etc/localtime:/etc/localtime \
+ -w $SCRIPTSDIR \
+ $imageName $command
diff --git a/src/pmdk/utils/docker/build-local.sh b/src/pmdk/utils/docker/build-local.sh
new file mode 100755
index 000000000..0fa5b2107
--- /dev/null
+++ b/src/pmdk/utils/docker/build-local.sh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2020, Intel Corporation
+
+#
+# build-local.sh - runs a Docker container from a Docker image with environment
+# prepared for building PMDK project and starts building PMDK.
+#
+# This script is for building PMDK locally (not on CI).
+#
+# Notes:
+# - run this script from its location or set the variable 'HOST_WORKDIR' to
+# where the root of the PMDK project is on the host machine.
+# - set variables 'OS' and 'OS_VER' properly to a system you want to build PMDK
+# on (for proper values take a look on the list of Dockerfiles at the
+# utils/docker/images directory), eg. OS=ubuntu, OS_VER=16.04.
+# - set 'KEEP_TEST_CONFIG' variable to 1 if you do not want the tests to be
+# reconfigured (your current test configuration will be preserved and used).
+# - tests with Device Dax are not supported by pcheck yet, so do not provide
+# these devices in your configuration.
+#
+
+set -e
+
+# Environment variables that can be customized (default values are after dash):
+export KEEP_CONTAINER=${KEEP_CONTAINER:-0}
+export KEEP_TEST_CONFIG=${KEEP_TEST_CONFIG:-0}
+export TEST_BUILD=${TEST_BUILD:-all}
+export REMOTE_TESTS=${REMOTE_TESTS:-1}
+export MAKE_PKG=${MAKE_PKG:-0}
+export EXTRA_CFLAGS=${EXTRA_CFLAGS}
+export EXTRA_CXXFLAGS=${EXTRA_CXXFLAGS:-}
+export PMDK_CC=${PMDK_CC:-gcc}
+export PMDK_CXX=${PMDK_CXX:-g++}
+export EXPERIMENTAL=${EXPERIMENTAL:-n}
+export VALGRIND=${VALGRIND:-1}
+export DOCKERHUB_REPO=${DOCKERHUB_REPO:-pmem/pmdk}
+export GITHUB_REPO=${GITHUB_REPO:-pmem/pmdk}
+
+if [[ -z "$OS" || -z "$OS_VER" ]]; then
+ echo "ERROR: The variables OS and OS_VER have to be set " \
+ "(eg. OS=ubuntu, OS_VER=16.04)."
+ exit 1
+fi
+
+if [[ -z "$HOST_WORKDIR" ]]; then
+ HOST_WORKDIR=$(readlink -f ../..)
+fi
+
+if [[ "$KEEP_CONTAINER" != "1" ]]; then
+ RM_SETTING=" --rm"
+fi
+
+imageName=${DOCKERHUB_REPO}:1.10-${OS}-${OS_VER}-${CI_CPU_ARCH}
+containerName=pmdk-${OS}-${OS_VER}
+
+if [[ $MAKE_PKG -eq 1 ]] ; then
+ command="./run-build-package.sh"
+else
+ command="./run-build.sh"
+fi
+
+if [ -n "$DNS_SERVER" ]; then DNS_SETTING=" --dns=$DNS_SERVER "; fi
+if [ -z "$NDCTL_ENABLE" ]; then ndctl_enable=; else ndctl_enable="--env NDCTL_ENABLE=$NDCTL_ENABLE"; fi
+
+WORKDIR=/pmdk
+SCRIPTSDIR=$WORKDIR/utils/docker
+
+# Check if we are running on a CI (Travis or GitHub Actions)
+[ -n "$GITHUB_ACTIONS" -o -n "$TRAVIS" ] && CI_RUN="YES" || CI_RUN="NO"
+
+echo Building ${OS}-${OS_VER}
+
+# Run a container with
+# - environment variables set (--env)
+# - host directory containing PMDK source mounted (-v)
+# - a tmpfs /tmp with the necessary size and permissions (--tmpfs)*
+# - working directory set (-w)
+#
+# * We need a tmpfs /tmp inside docker but we cannot run it with --privileged
+# and do it from inside, so we do using this docker-run option.
+# By default --tmpfs add nosuid,nodev,noexec to the mount flags, we don't
+# want that and just to make sure we add the usually default rw,relatime just
+# in case docker change the defaults.
+docker run --name=$containerName -ti \
+ $RM_SETTING \
+ $DNS_SETTING \
+ --env http_proxy=$http_proxy \
+ --env https_proxy=$https_proxy \
+ --env CC=$PMDK_CC \
+ --env CXX=$PMDK_CXX \
+ --env VALGRIND=$VALGRIND \
+ --env EXTRA_CFLAGS=$EXTRA_CFLAGS \
+ --env EXTRA_CXXFLAGS=$EXTRA_CXXFLAGS \
+ --env EXTRA_LDFLAGS=$EXTRA_LDFLAGS \
+ --env REMOTE_TESTS=$REMOTE_TESTS \
+ --env CONFIGURE_TESTS=$CONFIGURE_TESTS \
+ --env TEST_BUILD=$TEST_BUILD \
+ --env WORKDIR=$WORKDIR \
+ --env EXPERIMENTAL=$EXPERIMENTAL \
+ --env SCRIPTSDIR=$SCRIPTSDIR \
+ --env KEEP_TEST_CONFIG=$KEEP_TEST_CONFIG \
+ --env CI_RUN=$CI_RUN \
+ --env BLACKLIST_FILE=$BLACKLIST_FILE \
+ $ndctl_enable \
+ --tmpfs /tmp:rw,relatime,suid,dev,exec,size=6G \
+ -v $HOST_WORKDIR:$WORKDIR \
+ -v /etc/localtime:/etc/localtime \
+ $DAX_SETTING \
+ -w $SCRIPTSDIR \
+ $imageName $command
diff --git a/src/pmdk/utils/docker/configure-tests.sh b/src/pmdk/utils/docker/configure-tests.sh
new file mode 100755
index 000000000..23148ed4f
--- /dev/null
+++ b/src/pmdk/utils/docker/configure-tests.sh
@@ -0,0 +1,105 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# configure-tests.sh - is called inside a Docker container; configures tests
+# and ssh server for use during build of PMDK project.
+#
+
+set -e
+
+# Configure tests
+cat << EOF > $WORKDIR/src/test/testconfig.sh
+LONGDIR=LoremipsumdolorsitametconsecteturadipiscingelitVivamuslacinianibhattortordictumsollicitudinNullamvariusvestibulumligulaetegestaselitsemperidMaurisultriciesligulaeuipsumtinciduntluctusMorbimaximusvariusdolorid
+# this path is ~3000 characters long
+DIRSUFFIX="$LONGDIR/$LONGDIR/$LONGDIR/$LONGDIR/$LONGDIR"
+NON_PMEM_FS_DIR=/tmp
+PMEM_FS_DIR=/tmp
+PMEM_FS_DIR_FORCE_PMEM=1
+TEST_BUILD="debug nondebug"
+ENABLE_SUDO_TESTS=y
+TM=1
+EOF
+
+# Configure remote tests
+if [[ $REMOTE_TESTS -eq 1 ]]; then
+ echo "Configuring remote tests"
+ cat << EOF >> $WORKDIR/src/test/testconfig.sh
+NODE[0]=127.0.0.1
+NODE_WORKING_DIR[0]=/tmp/node0
+NODE_ADDR[0]=127.0.0.1
+NODE_ENV[0]="PMEM_IS_PMEM_FORCE=1"
+NODE[1]=127.0.0.1
+NODE_WORKING_DIR[1]=/tmp/node1
+NODE_ADDR[1]=127.0.0.1
+NODE_ENV[1]="PMEM_IS_PMEM_FORCE=1"
+NODE[2]=127.0.0.1
+NODE_WORKING_DIR[2]=/tmp/node2
+NODE_ADDR[2]=127.0.0.1
+NODE_ENV[2]="PMEM_IS_PMEM_FORCE=1"
+NODE[3]=127.0.0.1
+NODE_WORKING_DIR[3]=/tmp/node3
+NODE_ADDR[3]=127.0.0.1
+NODE_ENV[3]="PMEM_IS_PMEM_FORCE=1"
+TEST_BUILD="debug nondebug"
+TEST_PROVIDERS=sockets
+EOF
+
+ mkdir -p ~/.ssh/cm
+
+ cat << EOF >> ~/.ssh/config
+Host 127.0.0.1
+ StrictHostKeyChecking no
+ ControlPath ~/.ssh/cm/%r@%h:%p
+ ControlMaster auto
+ ControlPersist 10m
+EOF
+
+ if [ ! -f /etc/ssh/ssh_host_rsa_key ]
+ then
+ (echo $USERPASS | sudo -S ssh-keygen -t rsa -C $USER@$HOSTNAME -P '' -f /etc/ssh/ssh_host_rsa_key)
+ fi
+ echo $USERPASS | sudo -S sh -c 'cat /etc/ssh/ssh_host_rsa_key.pub >> /etc/ssh/authorized_keys'
+ ssh-keygen -t rsa -C $USER@$HOSTNAME -P '' -f ~/.ssh/id_rsa
+ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
+ chmod -R 700 ~/.ssh
+ chmod 640 ~/.ssh/authorized_keys
+ chmod 600 ~/.ssh/config
+
+ # Start ssh service
+ echo $USERPASS | sudo -S $START_SSH_COMMAND
+
+ ssh 127.0.0.1 exit 0
+else
+ echo "Skipping remote tests"
+ echo
+ echo "Removing all libfabric.pc files in order to simulate that libfabric is not installed:"
+ find /usr -name "libfabric.pc" 2>/dev/null || true
+ echo $USERPASS | sudo -S sh -c 'find /usr -name "libfabric.pc" -exec rm -f {} + 2>/dev/null'
+fi
+
+# Configure python tests
+ cat << EOF >> $WORKDIR/src/test/testconfig.py
+config = {
+ 'unittest_log_level': 1,
+ 'cacheline_fs_dir': '/tmp',
+ 'force_cacheline': True,
+ 'page_fs_dir': '/tmp',
+ 'force_page': False,
+ 'byte_fs_dir': '/tmp',
+ 'force_byte': True,
+ 'tm': True,
+ 'test_type': 'check',
+ 'granularity': 'all',
+ 'fs_dir_force_pmem': 0,
+ 'keep_going': False,
+ 'timeout': '3m',
+ 'build': ['debug', 'release'],
+ 'force_enable': None,
+ 'device_dax_path': [],
+ 'fail_on_skip': False,
+ 'enable_admin_tests': True
+ }
+EOF
+
diff --git a/src/pmdk/utils/docker/images/0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch b/src/pmdk/utils/docker/images/0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch
new file mode 100644
index 000000000..7377d07f6
--- /dev/null
+++ b/src/pmdk/utils/docker/images/0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch
@@ -0,0 +1,37 @@
+From d633d3b0a5f03be280efb80a69b9d5ed4e9c4d56 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=C5=81ukasz=20Stolarczuk?= <lukasz.stolarczuk@intel.com>
+Date: Tue, 14 Jul 2020 13:58:34 +0200
+Subject: [PATCH] fix generating gcov files and turn-off verbose log
+
+---
+ codecov | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/codecov b/codecov
+index e702ecd..0a2f4d8 100755
+--- a/codecov
++++ b/codecov
+@@ -1108,9 +1108,9 @@ then
+ if [ "$ft_gcovout" = "0" ];
+ then
+ # suppress gcov output
+- bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" >/dev/null 2>&1 || true
++ bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -execdir $gcov_exe -pb $gcov_arg {} \;" >/dev/null 2>&1 || true
+ else
+- bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -exec $gcov_exe -pb $gcov_arg {} +" || true
++ bash -c "find $proj_root -type f -name '*.gcno' $gcov_include $gcov_ignore -execdir $gcov_exe -pb $gcov_arg {} \;" || true
+ fi
+ else
+ say "${e}==>${x} gcov disabled"
+@@ -1425,7 +1425,7 @@ do
+ report_len=$(wc -c < "$file")
+ if [ "$report_len" -ne 0 ];
+ then
+- say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}"
++ #say " ${g}+${x} $file ${e}bytes=$(echo "$report_len" | tr -d ' ')${x}"
+ # append to to upload
+ _filename=$(basename "$file")
+ if [ "${_filename##*.}" = 'gcov' ];
+--
+2.25.1
+
diff --git a/src/pmdk/utils/docker/images/Dockerfile.fedora-31 b/src/pmdk/utils/docker/images/Dockerfile.fedora-31
new file mode 100644
index 000000000..a699fee85
--- /dev/null
+++ b/src/pmdk/utils/docker/images/Dockerfile.fedora-31
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# Dockerfile - a 'recipe' for Docker to build an image of fedora-based
+# environment for building the PMDK project.
+#
+
+# Pull base image
+FROM fedora:31
+MAINTAINER piotr.balcer@intel.com
+
+# libfabric (optional if libfabric-dev >= 1.4.2 is installed)
+ENV FABRIC_DEPS "\
+ autoconf \
+ automake \
+ libtool \
+ wget"
+
+ENV VALGRIND_DEPS "\
+ autoconf \
+ automake \
+ file \
+ findutils \
+ git"
+
+# pmdk base
+ENV BASE_DEPS "\
+ git \
+ daxctl-devel \
+ make \
+ ndctl-devel \
+ pkgconfig"
+
+# benchmarks (optional)
+ENV BENCH_DEPS "\
+ glib2-devel"
+
+# examples (optional)
+ENV EXAMPLES_DEPS "\
+ fuse \
+ fuse-devel \
+ ncurses-devel \
+ libuv-devel"
+
+# documentation (optional)
+ENV DOC_DEPS "\
+ pandoc"
+
+# tests
+ENV TESTS_DEPS "\
+ bc \
+ gdb \
+ libunwind-devel \
+ ndctl \
+ openssh-server \
+ strace"
+
+# packaging
+ENV PACKAGING_DEPS "\
+ rpm-build \
+ rpm-build-libs \
+ rpmdevtools"
+
+# Coverity
+ENV COVERITY_DEPS "\
+ gcc \
+ wget"
+
+# misc
+ENV MISC_DEPS "\
+ clang \
+ hub \
+ lbzip2 \
+ man \
+ python3-flake8 \
+ rsync \
+ shadow-utils \
+ sudo \
+ tar \
+ which \
+ xmlto"
+
+# Copy install valgrind script
+COPY install-valgrind.sh install-valgrind.sh
+
+# Copy install libfabric script
+COPY install-libfabric.sh install-libfabric.sh
+
+RUN dnf update -y && dnf install -y \
+ $FABRIC_DEPS \
+ $VALGRIND_DEPS \
+ $BASE_DEPS \
+ $BENCH_DEPS \
+ $EXAMPLES_DEPS \
+ $DOC_DEPS \
+ $TESTS_DEPS \
+ $PACKAGING_DEPS \
+ $COVERITY_DEPS \
+ $MISC_DEPS \
+ $TESTS_DEPS \
+ && ./install-valgrind.sh fedora \
+ && ./install-libfabric.sh fedora \
+ && dnf clean all
+
+# Add user
+ENV USER pmdkuser
+ENV USERPASS pmdkpass
+RUN useradd -m $USER
+RUN echo "$USER:$USERPASS" | chpasswd
+RUN gpasswd wheel -a $USER
+RUN echo "%wheel ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+USER $USER
+
+# Set required environment variables
+ENV OS fedora
+ENV OS_VER 31
+ENV START_SSH_COMMAND /usr/sbin/sshd
+ENV PACKAGE_MANAGER rpm
+ENV NOTTY 1
diff --git a/src/pmdk/utils/docker/images/Dockerfile.ubuntu-19.10 b/src/pmdk/utils/docker/images/Dockerfile.ubuntu-19.10
new file mode 100644
index 000000000..9b61f8953
--- /dev/null
+++ b/src/pmdk/utils/docker/images/Dockerfile.ubuntu-19.10
@@ -0,0 +1,121 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# Dockerfile - a 'recipe' for Docker to build an image of ubuntu-based
+# environment for building the PMDK project.
+#
+
+# Pull base image
+FROM ubuntu:19.10
+MAINTAINER piotr.balcer@intel.com
+
+ENV DEBIAN_FRONTEND noninteractive
+
+# Additional parameters to build docker without building components
+ARG SKIP_SCRIPTS_DOWNLOAD
+
+# libfabric (optional if libfabric-dev >= 1.4.2 is installed)
+ENV FABRIC_DEPS "autoconf \
+ automake \
+ build-essential \
+ libtool \
+ unzip \
+ wget"
+
+ENV VALGRIND_DEPS "autoconf \
+ automake \
+ build-essential \
+ git"
+
+# pmdk base
+ENV BASE_DEPS "build-essential \
+ git \
+ libdaxctl-dev \
+ libndctl-dev \
+ pkg-config"
+
+# benchmarks (optional)
+ENV BENCH_DEPS libglib2.0-dev
+
+# examples (optional)
+ENV EXAMPLES_DEPS "libfuse-dev \
+ libncurses5-dev \
+ libuv1-dev"
+
+# documentation (optional)
+ENV DOC_DEPS pandoc
+
+# tests
+ENV TESTS_DEPS "bc \
+ gdb \
+ libc6-dbg \
+ libunwind-dev \
+ ndctl \
+ python3 \
+ ssh \
+ strace"
+
+# packaging
+ENV PACKAGING_DEPS "debhelper \
+ devscripts \
+ fakeroot"
+
+# CodeCov
+ENV CODECOV_DEPS curl
+
+# Coverity
+ENV COVERITY_DEPS ruby gcc g++ wget
+
+# misc
+ENV MISC_DEPS "clang \
+ clang-format \
+ flake8 \
+ sudo \
+ whois"
+
+# Copy install valgrind script
+COPY install-valgrind.sh install-valgrind.sh
+
+# Copy install libfabric script
+COPY install-libfabric.sh install-libfabric.sh
+
+# Copy codecov patch and script to download scripts required in run-*.sh
+COPY download-scripts.sh download-scripts.sh
+COPY 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch \
+ 0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch
+
+# Update the Apt cache and install basic tools
+RUN apt-get update && apt-get dist-upgrade -y \
+ && apt-get install -y --no-install-recommends \
+ $FABRIC_DEPS \
+ $VALGRIND_DEPS \
+ $BASE_DEPS \
+ $BENCH_DEPS \
+ $EXAMPLES_DEPS \
+ $DOC_DEPS \
+ $TESTS_DEPS \
+ $PACKAGING_DEPS \
+ $CODECOV_DEPS \
+ $COVERITY_DEPS \
+ $MISC_DEPS \
+ && ./install-valgrind.sh ubuntu \
+ && ./install-libfabric.sh \
+ && ./download-scripts.sh \
+ && rm -rf /var/lib/apt/lists/*
+
+# Add user
+ENV USER pmdkuser
+ENV USERPASS pmdkpass
+RUN useradd -m $USER -g sudo -p `mkpasswd $USERPASS`
+RUN echo "%sudo ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
+
+# switch user
+USER $USER
+
+# Set required environment variables
+ENV OS ubuntu
+ENV OS_VER 19.10
+ENV START_SSH_COMMAND service ssh start
+ENV PACKAGE_MANAGER dpkg
+ENV NOTTY 1
diff --git a/src/pmdk/utils/docker/images/README b/src/pmdk/utils/docker/images/README
new file mode 100644
index 000000000..0b8c551e4
--- /dev/null
+++ b/src/pmdk/utils/docker/images/README
@@ -0,0 +1,6 @@
+Persistent Memory Development Kit
+
+This is utils/docker/images/README.
+
+Scripts in this directory let you prepare Docker images for building
+PMDK project under specified OS (ubuntu, fedora).
diff --git a/src/pmdk/utils/docker/images/build-image.sh b/src/pmdk/utils/docker/images/build-image.sh
new file mode 100755
index 000000000..b9e7a2a4b
--- /dev/null
+++ b/src/pmdk/utils/docker/images/build-image.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# build-image.sh <OS-VER> <ARCH> - prepares a Docker image with <OS>-based
+# environment intended for the <ARCH> CPU architecture
+# designed for building PMDK project, according to
+# the Dockerfile.<OS-VER> file located in the same directory.
+#
+# The script can be run locally.
+#
+
+set -e
+
+OS_VER=$1
+CPU_ARCH=$2
+
+function usage {
+ echo "Usage:"
+ echo " build-image.sh <OS-VER> <ARCH>"
+ echo "where:"
+ echo " <OS-VER> - can be for example 'ubuntu-19.10' provided "\
+ "a Dockerfile named 'Dockerfile.ubuntu-19.10' "\
+ "exists in the current directory and"
+ echo " <ARCH> - is a CPU architecture, for example 'x86_64'"
+}
+
+# Check if two first arguments are not empty
+if [[ -z "$2" ]]; then
+ usage
+ exit 1
+fi
+
+# Check if the file Dockerfile.OS-VER exists
+if [[ ! -f "Dockerfile.$OS_VER" ]]; then
+ echo "Error: Dockerfile.$OS_VER does not exist."
+ echo
+ usage
+ exit 1
+fi
+
+if [[ -z "${DOCKERHUB_REPO}" ]]; then
+ echo "Error: DOCKERHUB_REPO environment variable is not set"
+ exit 1
+fi
+
+# Build a Docker image tagged with ${DOCKERHUB_REPO}:OS-VER-ARCH
+tag=${DOCKERHUB_REPO}:1.10-${OS_VER}-${CPU_ARCH}
+docker build -t $tag \
+ --build-arg http_proxy=$http_proxy \
+ --build-arg https_proxy=$https_proxy \
+ -f Dockerfile.$OS_VER .
diff --git a/src/pmdk/utils/docker/images/download-scripts.sh b/src/pmdk/utils/docker/images/download-scripts.sh
new file mode 100755
index 000000000..fae37b464
--- /dev/null
+++ b/src/pmdk/utils/docker/images/download-scripts.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020, Intel Corporation
+
+#
+# download-scripts.sh - downloads specific version of codecov's bash
+# script to generate and upload reports. It's useful,
+# since unverified version may break coverage results.
+#
+
+set -e
+
+# master: Merge pull request #342 from codecov/revert-proj-name-..., 18.08.2020
+CODECOV_VERSION="e877c1280cc6e902101fb5df2981ed1c962da7f0"
+
+if [ "${SKIP_SCRIPTS_DOWNLOAD}" ]; then
+ echo "Variable 'SKIP_SCRIPTS_DOWNLOAD' is set; skipping scripts' download"
+ exit
+fi
+
+mkdir -p /opt/scripts
+
+# Download codecov's bash script
+git clone https://github.com/codecov/codecov-bash
+cd codecov-bash
+git checkout $CODECOV_VERSION
+
+git apply ../0001-fix-generating-gcov-files-and-turn-off-verbose-log.patch
+mv -v codecov /opt/scripts/codecov
+
+cd ..
+rm -rf codecov-bash
diff --git a/src/pmdk/utils/docker/images/install-libfabric.sh b/src/pmdk/utils/docker/images/install-libfabric.sh
new file mode 100755
index 000000000..355f24525
--- /dev/null
+++ b/src/pmdk/utils/docker/images/install-libfabric.sh
@@ -0,0 +1,40 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# install-libfabric.sh - installs a customized version of libfabric
+#
+
+set -e
+
+OS=$1
+
+# Keep in sync with requirements in src/common.inc.
+libfabric_ver=1.4.2
+libfabric_url=https://github.com/ofiwg/libfabric/archive
+libfabric_dir=libfabric-$libfabric_ver
+libfabric_tarball=v${libfabric_ver}.zip
+wget "${libfabric_url}/${libfabric_tarball}"
+unzip $libfabric_tarball
+
+cd $libfabric_dir
+
+# XXX HACK HACK HACK
+# Disable use of spin locks in libfabric.
+#
+# spinlocks do not play well (IOW at all) with cpu-constrained environments,
+# like GitHub Actions, and this leads to timeouts of some PMDK's tests.
+# This change speeds up pmempool_sync_remote/TEST28-31 by a factor of 20-30.
+#
+perl -pi -e 's/have_spinlock=1/have_spinlock=0/' configure.ac
+# XXX HACK HACK HACK
+
+./autogen.sh
+./configure --prefix=/usr --enable-sockets
+make -j$(nproc)
+make -j$(nproc) install
+
+cd ..
+rm -f ${libfabric_tarball}
+rm -rf ${libfabric_dir}
diff --git a/src/pmdk/utils/docker/images/install-libndctl.sh b/src/pmdk/utils/docker/images/install-libndctl.sh
new file mode 100755
index 000000000..fc8cee3fb
--- /dev/null
+++ b/src/pmdk/utils/docker/images/install-libndctl.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2019, Intel Corporation
+
+#
+# install-libndctl.sh - installs libndctl
+#
+
+set -e
+
+OS=$2
+
+echo "==== clone ndctl repo ===="
+git clone https://github.com/pmem/ndctl.git
+cd ndctl
+git checkout $1
+
+if [ "$OS" = "fedora" ]; then
+
+echo "==== setup rpmbuild tree ===="
+rpmdev-setuptree
+
+RPMDIR=$HOME/rpmbuild/
+VERSION=$(./git-version)
+SPEC=./rhel/ndctl.spec
+
+echo "==== create source tarball ====="
+git archive --format=tar --prefix="ndctl-${VERSION}/" HEAD | gzip > "$RPMDIR/SOURCES/ndctl-${VERSION}.tar.gz"
+
+echo "==== build ndctl ===="
+./autogen.sh
+./configure --disable-docs
+make -j$(nproc)
+
+echo "==== build ndctl packages ===="
+rpmbuild -ba $SPEC
+
+echo "==== install ndctl packages ===="
+RPM_ARCH=$(uname -m)
+rpm -i $RPMDIR/RPMS/$RPM_ARCH/*.rpm
+
+echo "==== cleanup ===="
+rm -rf $RPMDIR
+
+else
+
+echo "==== build ndctl ===="
+./autogen.sh
+./configure --disable-docs
+make -j$(nproc)
+
+echo "==== install ndctl ===="
+make -j$(nproc) install
+
+echo "==== cleanup ===="
+
+fi
+
+cd ..
+rm -rf ndctl
diff --git a/src/pmdk/utils/docker/images/install-valgrind.sh b/src/pmdk/utils/docker/images/install-valgrind.sh
new file mode 100755
index 000000000..97babcb67
--- /dev/null
+++ b/src/pmdk/utils/docker/images/install-valgrind.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# install-valgrind.sh - installs valgrind for persistent memory
+#
+
+set -e
+
+OS=$1
+
+install_upstream_from_distro() {
+ case "$OS" in
+ fedora) dnf install -y valgrind ;;
+ ubuntu) apt-get install -y --no-install-recommends valgrind ;;
+ *) return 1 ;;
+ esac
+}
+
+install_upstream_3_16_1() {
+ git clone git://sourceware.org/git/valgrind.git
+ cd valgrind
+ # valgrind v3.16.1 upstream
+ git checkout VALGRIND_3_16_BRANCH
+ ./autogen.sh
+ ./configure
+ make -j$(nproc)
+ make -j$(nproc) install
+ cd ..
+ rm -rf valgrind
+}
+
+install_custom-pmem_from_source() {
+ git clone https://github.com/pmem/valgrind.git
+ cd valgrind
+ # valgrind v3.15 with pmemcheck
+ # 2020.04.01 Merge pull request #78 from marcinslusarz/opt3
+ git checkout 759686fd66cc0105df8311cfe676b0b2f9e89196
+ ./autogen.sh
+ ./configure
+ make -j$(nproc)
+ make -j$(nproc) install
+ cd ..
+ rm -rf valgrind
+}
+
+ARCH=$(uname -m)
+case "$ARCH" in
+ ppc64le) install_upstream_3_16_1 ;;
+ *) install_custom-pmem_from_source ;;
+esac
diff --git a/src/pmdk/utils/docker/images/push-image.sh b/src/pmdk/utils/docker/images/push-image.sh
new file mode 100755
index 000000000..03b935213
--- /dev/null
+++ b/src/pmdk/utils/docker/images/push-image.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# push-image.sh - pushes the Docker image to the Docker Hub.
+#
+# The script utilizes $DOCKERHUB_USER and $DOCKERHUB_PASSWORD variables
+# to log in to Docker Hub. The variables can be set in the Travis project's
+# configuration for automated builds.
+#
+
+set -e
+
+source $(dirname $0)/../set-ci-vars.sh
+
+if [[ -z "$OS" ]]; then
+ echo "OS environment variable is not set"
+ exit 1
+fi
+
+if [[ -z "$OS_VER" ]]; then
+ echo "OS_VER environment variable is not set"
+ exit 1
+fi
+
+if [[ -z "$CI_CPU_ARCH" ]]; then
+ echo "CI_CPU_ARCH environment variable is not set"
+ exit 1
+fi
+
+if [[ -z "${DOCKERHUB_REPO}" ]]; then
+ echo "DOCKERHUB_REPO environment variable is not set"
+ exit 1
+fi
+
+TAG="1.10-${OS}-${OS_VER}-${CI_CPU_ARCH}"
+
+# Check if the image tagged with pmdk/OS-VER exists locally
+if [[ ! $(docker images -a | awk -v pattern="^${DOCKERHUB_REPO}:${TAG}\$" \
+ '$1":"$2 ~ pattern') ]]
+then
+ echo "ERROR: Docker image tagged ${DOCKERHUB_REPO}:${TAG} does not exists locally."
+ exit 1
+fi
+
+# Log in to the Docker Hub
+docker login -u="$DOCKERHUB_USER" -p="$DOCKERHUB_PASSWORD"
+
+# Push the image to the repository
+docker push ${DOCKERHUB_REPO}:${TAG}
diff --git a/src/pmdk/utils/docker/ppc64le.blacklist b/src/pmdk/utils/docker/ppc64le.blacklist
new file mode 100644
index 000000000..6002ad91f
--- /dev/null
+++ b/src/pmdk/utils/docker/ppc64le.blacklist
@@ -0,0 +1,19 @@
+ex_librpmem_basic
+ex_librpmem_hello
+ex_librpmem_manpage
+libpmempool_rm_remote
+obj_basic_integration
+obj_check_remote
+obj_ctl_debug
+obj_mem
+obj_memcheck_register
+obj_pmalloc_mt
+obj_rpmem_basic_integration
+obj_rpmem_heap_interrupt
+obj_rpmem_heap_state
+obj_ulog_size
+pmempool_create
+pmempool_sync_remote
+pmempool_transform_remote
+rpmem_basic
+rpmem_fip
diff --git a/src/pmdk/utils/docker/prepare-for-build.sh b/src/pmdk/utils/docker/prepare-for-build.sh
new file mode 100755
index 000000000..f18c18c68
--- /dev/null
+++ b/src/pmdk/utils/docker/prepare-for-build.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# prepare-for-build.sh - is called inside a Docker container; prepares
+# the environment inside a Docker container for
+# running build of PMDK project.
+#
+
+set -e
+
+# This should be run only on CIs
+if [ "$CI_RUN" == "YES" ]; then
+ # Make sure $WORKDIR has correct access rights
+ # - set them to the current UID and GID
+ echo $USERPASS | sudo -S chown -R $(id -u).$(id -g) $WORKDIR
+fi
+
+# Configure tests (e.g. ssh for remote tests) unless the current configuration
+# should be preserved
+KEEP_TEST_CONFIG=${KEEP_TEST_CONFIG:-0}
+if [[ "$KEEP_TEST_CONFIG" == 0 ]]; then
+ ./configure-tests.sh
+fi
diff --git a/src/pmdk/utils/docker/pull-or-rebuild-image.sh b/src/pmdk/utils/docker/pull-or-rebuild-image.sh
new file mode 100755
index 000000000..a3a23cdd1
--- /dev/null
+++ b/src/pmdk/utils/docker/pull-or-rebuild-image.sh
@@ -0,0 +1,112 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# pull-or-rebuild-image.sh - rebuilds the Docker image used in the
+# current Travis build if necessary.
+#
+# The script rebuilds the Docker image if the Dockerfile for the current
+# OS version (Dockerfile.${OS}-${OS_VER}) or any .sh script from the directory
+# with Dockerfiles were modified and committed.
+#
+# If the Travis build is not of the "pull_request" type (i.e. in case of
+# merge after pull_request) and it succeed, the Docker image should be pushed
+# to the Docker Hub repository. An empty file is created to signal that to
+# further scripts.
+#
+# If the Docker image does not have to be rebuilt, it will be pulled from
+# Docker Hub.
+#
+
+set -e
+
+source $(dirname $0)/set-ci-vars.sh
+source $(dirname $0)/set-vars.sh
+
+if [[ "$CI_EVENT_TYPE" != "cron" && "$CI_BRANCH" != "coverity_scan" \
+ && "$COVERITY" -eq 1 ]]; then
+ echo "INFO: Skip Coverity scan job if build is triggered neither by " \
+ "'cron' nor by a push to 'coverity_scan' branch"
+ exit 0
+fi
+
+if [[ ( "$CI_EVENT_TYPE" == "cron" || "$CI_BRANCH" == "coverity_scan" )\
+ && "$COVERITY" -ne 1 ]]; then
+ echo "INFO: Skip regular jobs if build is triggered either by 'cron'" \
+ " or by a push to 'coverity_scan' branch"
+ exit 0
+fi
+
+if [[ -z "$OS" || -z "$OS_VER" ]]; then
+ echo "ERROR: The variables OS and OS_VER have to be set properly " \
+ "(eg. OS=ubuntu, OS_VER=16.04)."
+ exit 1
+fi
+
+if [[ -z "$HOST_WORKDIR" ]]; then
+ echo "ERROR: The variable HOST_WORKDIR has to contain a path to " \
+ "the root of the PMDK project on the host machine"
+ exit 1
+fi
+
+# Find all the commits for the current build
+if [ -n "$CI_COMMIT_RANGE" ]; then
+ commits=$(git rev-list $CI_COMMIT_RANGE)
+else
+ commits=$CI_COMMIT
+fi
+
+echo "Commits in the commit range:"
+for commit in $commits; do echo $commit; done
+
+# Get the list of files modified by the commits
+files=$(for commit in $commits; do git diff-tree --no-commit-id --name-only \
+ -r $commit; done | sort -u)
+echo "Files modified within the commit range:"
+for file in $files; do echo $file; done
+
+# Path to directory with Dockerfiles and image building scripts
+images_dir_name=images
+base_dir=utils/docker/$images_dir_name
+
+# Check if committed file modifications require the Docker image to be rebuilt
+for file in $files; do
+ # Check if modified files are relevant to the current build
+ if [[ $file =~ ^($base_dir)\/Dockerfile\.($OS)-($OS_VER)$ ]] \
+ || [[ $file =~ ^($base_dir)\/.*\.sh$ ]]
+ then
+ # Rebuild Docker image for the current OS version
+ echo "Rebuilding the Docker image for the Dockerfile.$OS-$OS_VER"
+ pushd $images_dir_name
+ ./build-image.sh ${OS}-${OS_VER} ${CI_CPU_ARCH}
+ popd
+
+ # Check if the image has to be pushed to Docker Hub
+ # (i.e. the build is triggered by commits to the $GITHUB_REPO
+ # repository's stable-* or master branch, and the Travis build is not
+ # of the "pull_request" type). In that case, create the empty
+ # file.
+ if [[ "$CI_REPO_SLUG" == "$GITHUB_REPO" \
+ && ($CI_BRANCH == stable-* || $CI_BRANCH == devel-* || $CI_BRANCH == master) \
+ && $CI_EVENT_TYPE != "pull_request" \
+ && $PUSH_IMAGE == "1" ]]
+ then
+ echo "The image will be pushed to Docker Hub"
+ touch $CI_FILE_PUSH_IMAGE_TO_REPO
+ else
+ echo "Skip pushing the image to Docker Hub"
+ fi
+
+ if [[ $PUSH_IMAGE == "1" ]]
+ then
+ echo "Skip build package check if image has to be pushed"
+ touch $CI_FILE_SKIP_BUILD_PKG_CHECK
+ fi
+ exit 0
+ fi
+done
+
+# Getting here means rebuilding the Docker image is not required.
+# Pull the image from Docker Hub.
+docker pull ${DOCKERHUB_REPO}:1.10-${OS}-${OS_VER}-${CI_CPU_ARCH}
diff --git a/src/pmdk/utils/docker/run-build-package.sh b/src/pmdk/utils/docker/run-build-package.sh
new file mode 100755
index 000000000..5141904aa
--- /dev/null
+++ b/src/pmdk/utils/docker/run-build-package.sh
@@ -0,0 +1,47 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2019, Intel Corporation
+
+#
+# run-build-package.sh - is called inside a Docker container; prepares
+# the environment and starts a build of PMDK project.
+#
+
+set -e
+
+# Prepare build enviromnent
+./prepare-for-build.sh
+
+# Create fake tag, so that package has proper 'version' field
+git config user.email "test@package.com"
+git config user.name "test package"
+git tag -a 1.4.99 -m "1.4" HEAD~1 || true
+
+# Build all and run tests
+cd $WORKDIR
+export PCHECK_OPTS="-j2 BLACKLIST_FILE=${BLACKLIST_FILE}"
+make -j$(nproc) $PACKAGE_MANAGER
+
+# Install packages
+if [[ "$PACKAGE_MANAGER" == "dpkg" ]]; then
+ cd $PACKAGE_MANAGER
+ echo $USERPASS | sudo -S dpkg --install *.deb
+else
+ RPM_ARCH=$(uname -m)
+ cd $PACKAGE_MANAGER/$RPM_ARCH
+ echo $USERPASS | sudo -S rpm --install *.rpm
+fi
+
+# Compile and run standalone test
+cd $WORKDIR/utils/docker/test_package
+make -j$(nproc) LIBPMEMOBJ_MIN_VERSION=1.4
+./test_package testfile1
+
+# Use pmreorder installed in the system
+pmreorder_version="$(pmreorder -v)"
+pmreorder_pattern="pmreorder\.py .+$"
+(echo "$pmreorder_version" | grep -Ev "$pmreorder_pattern") && echo "pmreorder version failed" && exit 1
+
+touch testfile2
+touch logfile1
+pmreorder -p testfile2 -l logfile1
diff --git a/src/pmdk/utils/docker/run-build.sh b/src/pmdk/utils/docker/run-build.sh
new file mode 100755
index 000000000..78edf09ec
--- /dev/null
+++ b/src/pmdk/utils/docker/run-build.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+
+#
+# run-build.sh - is called inside a Docker container; prepares the environment
+# and starts a build of PMDK project.
+#
+
+set -e
+
+# Prepare build environment
+./prepare-for-build.sh
+
+# Build all and run tests
+cd $WORKDIR
+if [ "$SRC_CHECKERS" != "0" ]; then
+ make -j$(nproc) check-license
+ make -j$(nproc) cstyle
+fi
+
+make -j$(nproc)
+make -j$(nproc) test
+# do not change -j2 to -j$(nproc) in case of tests (make check/pycheck)
+make -j2 pcheck TEST_BUILD=$TEST_BUILD
+# do not change -j2 to -j$(nproc) in case of tests (make check/pycheck)
+make -j2 pycheck
+make -j$(nproc) DESTDIR=/tmp source
+
+# Create PR with generated docs
+if [[ "$AUTO_DOC_UPDATE" == "1" ]]; then
+ echo "Running auto doc update"
+ ./utils/docker/run-doc-update.sh
+fi
diff --git a/src/pmdk/utils/docker/run-coverage.sh b/src/pmdk/utils/docker/run-coverage.sh
new file mode 100755
index 000000000..b6f7ed0a8
--- /dev/null
+++ b/src/pmdk/utils/docker/run-coverage.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2020, Intel Corporation
+
+#
+# run-coverage.sh - is called inside a Docker container; runs tests
+# to measure code coverage and sends report to codecov.io
+#
+
+set -e
+
+# Get and prepare PMDK source
+./prepare-for-build.sh
+
+# Hush error messages, mainly from Valgrind
+export UT_DUMP_LINES=0
+
+# Skip printing mismatched files for tests with Valgrind
+export UT_VALGRIND_SKIP_PRINT_MISMATCHED=1
+
+# Build all and run tests
+cd $WORKDIR
+make -j$(nproc) COVERAGE=1
+make -j$(nproc) test COVERAGE=1
+
+# XXX: unfortunately valgrind raports issues in coverage instrumentation
+# which we have to ignore (-k flag), also there is dependency between
+# local and remote tests (which cannot be easily removed) we have to
+# run local and remote tests separately
+cd src/test
+# do not change -j2 to -j$(nproc) in case of tests (make check/pycheck)
+make -kj2 pcheck-local-quiet TEST_BUILD=debug || true
+make check-remote-quiet TEST_BUILD=debug || true
+# do not change -j2 to -j$(nproc) in case of tests (make check/pycheck)
+make -j2 pycheck TEST_BUILD=debug || true
+cd ../..
+
+# prepare flag for codecov report to differentiate builds
+flag=tests
+[ -n "$GITHUB_ACTIONS" ] && flag=GHA
+[ -n "$TRAVIS" ] && flag=Travis
+
+# run gcov exe, using codecov's bash (remove parsed coverage files, set flag and exit 1 if not successful)
+/opt/scripts/codecov -c -F ${flag} -Z
+
+printf "check for any leftover gcov files\n"
+leftover_files=$(find . -name "*.gcov" | wc -l)
+if [[ $leftover_files > 0 ]]; then
+ # display found files and exit with error (they all should be parsed)
+ find . -name "*.gcov"
+ return 1
+fi
diff --git a/src/pmdk/utils/docker/run-coverity.sh b/src/pmdk/utils/docker/run-coverity.sh
new file mode 100755
index 000000000..140fa753d
--- /dev/null
+++ b/src/pmdk/utils/docker/run-coverity.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2020, Intel Corporation
+
+#
+# run-coverity.sh - runs the Coverity scan build
+#
+
+set -e
+
+if [[ "$CI_REPO_SLUG" != "$GITHUB_REPO" \
+ && ( "$COVERITY_SCAN_NOTIFICATION_EMAIL" == "" \
+ || "$COVERITY_SCAN_TOKEN" == "" ) ]]; then
+ echo
+ echo "Skipping Coverity build:"\
+ "COVERITY_SCAN_TOKEN=\"$COVERITY_SCAN_TOKEN\" or"\
+ "COVERITY_SCAN_NOTIFICATION_EMAIL="\
+ "\"$COVERITY_SCAN_NOTIFICATION_EMAIL\" is not set"
+ exit 0
+fi
+
+# Prepare build environment
+./prepare-for-build.sh
+
+CERT_FILE=/etc/ssl/certs/ca-certificates.crt
+TEMP_CF=$(mktemp)
+cp $CERT_FILE $TEMP_CF
+
+# Download Coverity certificate
+echo -n | openssl s_client -connect scan.coverity.com:443 | \
+ sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | \
+ tee -a $TEMP_CF
+
+echo $USERPASS | sudo -S mv $TEMP_CF $CERT_FILE
+
+export COVERITY_SCAN_PROJECT_NAME="$CI_REPO_SLUG"
+[[ "$CI_EVENT_TYPE" == "cron" ]] \
+ && export COVERITY_SCAN_BRANCH_PATTERN="master" \
+ || export COVERITY_SCAN_BRANCH_PATTERN="coverity_scan"
+export COVERITY_SCAN_BUILD_COMMAND="make -j$(nproc) all"
+
+cd $WORKDIR
+
+#
+# Run the Coverity scan
+#
+
+# The 'travisci_build_coverity_scan.sh' script requires the following
+# environment variables to be set:
+# - TRAVIS_BRANCH - has to contain the name of the current branch
+# - TRAVIS_PULL_REQUEST - has to be set to 'true' in case of pull requests
+#
+export TRAVIS_BRANCH=${CI_BRANCH}
+[ "${CI_EVENT_TYPE}" == "pull_request" ] && export TRAVIS_PULL_REQUEST="true"
+
+# XXX: Patch the Coverity script.
+# Recently, this script regularly exits with an error, even though
+# the build is successfully submitted. Probably because the status code
+# is missing in response, or it's not 201.
+# Changes:
+# 1) change the expected status code to 200 and
+# 2) print the full response string.
+#
+# This change should be reverted when the Coverity script is fixed.
+#
+# The previous version was:
+# curl -s https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh | bash
+
+wget https://scan.coverity.com/scripts/travisci_build_coverity_scan.sh
+patch < utils/docker/0001-travis-fix-travisci_build_coverity_scan.sh.patch
+bash ./travisci_build_coverity_scan.sh
diff --git a/src/pmdk/utils/docker/run-doc-update.sh b/src/pmdk/utils/docker/run-doc-update.sh
new file mode 100755
index 000000000..132315eb8
--- /dev/null
+++ b/src/pmdk/utils/docker/run-doc-update.sh
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019-2020, Intel Corporation
+
+set -e
+
+source `dirname $0`/valid-branches.sh
+
+BOT_NAME="pmem-bot"
+USER_NAME="pmem"
+REPO_NAME="pmdk"
+
+ORIGIN="https://${DOC_UPDATE_GITHUB_TOKEN}@github.com/${BOT_NAME}/${REPO_NAME}"
+UPSTREAM="https://github.com/${USER_NAME}/${REPO_NAME}"
+# master or stable-* branch
+TARGET_BRANCH=${CI_BRANCH}
+VERSION=${TARGET_BRANCHES[$TARGET_BRANCH]}
+
+if [ -z $VERSION ]; then
+ echo "Target location for branch $TARGET_BRANCH is not defined."
+ exit 1
+fi
+
+# Clone bot repo
+git clone ${ORIGIN}
+cd ${REPO_NAME}
+git remote add upstream ${UPSTREAM}
+
+git config --local user.name ${BOT_NAME}
+git config --local user.email "pmem-bot@intel.com"
+
+git remote update
+git checkout -B ${TARGET_BRANCH} upstream/${TARGET_BRANCH}
+
+# Copy man & PR web md
+cd ./doc
+make -j$(nproc) web
+cd ..
+
+mv ./doc/web_linux ../
+mv ./doc/web_windows ../
+mv ./doc/generated/libs_map.yml ../
+
+# Checkout gh-pages and copy docs
+GH_PAGES_NAME="gh-pages-for-${TARGET_BRANCH}"
+git checkout -B $GH_PAGES_NAME upstream/gh-pages
+git clean -dfx
+
+rsync -a ../web_linux/ ./manpages/linux/${VERSION}/
+rsync -a ../web_windows/ ./manpages/windows/${VERSION}/ \
+ --exclude='librpmem' \
+ --exclude='rpmemd' --exclude='pmreorder' \
+ --exclude='daxio'
+
+rm -r ../web_linux
+rm -r ../web_windows
+
+if [ $TARGET_BRANCH = "master" ]; then
+ [ ! -d _data ] && mkdir _data
+ cp ../libs_map.yml _data
+fi
+
+# Add and push changes.
+# git commit command may fail if there is nothing to commit.
+# In that case we want to force push anyway (there might be open pull request
+# with changes which were reverted).
+git add -A
+git commit -m "doc: automatic gh-pages docs update" && true
+git push -f ${ORIGIN} $GH_PAGES_NAME
+
+GITHUB_TOKEN=${DOC_UPDATE_GITHUB_TOKEN} hub pull-request -f \
+ -b ${USER_NAME}:gh-pages \
+ -h ${BOT_NAME}:${GH_PAGES_NAME} \
+ -m "doc: automatic gh-pages docs update" && true
+
+exit 0
diff --git a/src/pmdk/utils/docker/set-ci-vars.sh b/src/pmdk/utils/docker/set-ci-vars.sh
new file mode 100755
index 000000000..af41a753e
--- /dev/null
+++ b/src/pmdk/utils/docker/set-ci-vars.sh
@@ -0,0 +1,96 @@
+#!/usr/bin/env bash
+#
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2020, Intel Corporation
+
+#
+# set-ci-vars.sh -- set CI variables common for both:
+# Travis and GitHub Actions CIs
+#
+
+set -e
+
+function get_commit_range_from_last_merge {
+ # get commit id of the last merge
+ LAST_MERGE=$(git log --merges --pretty=%H -1)
+ LAST_COMMIT=$(git log --pretty=%H -1)
+ if [ "$LAST_MERGE" == "$LAST_COMMIT" ]; then
+ # GitHub Actions commits its own merge in case of pull requests
+ # so the first merge commit has to be skipped.
+ LAST_MERGE=$(git log --merges --pretty=%H -2 | tail -n1)
+ fi
+ if [ "$LAST_MERGE" == "" ]; then
+ # possible in case of shallow clones
+ # or new repos with no merge commits yet
+ # - pick up the first commit
+ LAST_MERGE=$(git log --pretty=%H | tail -n1)
+ fi
+ COMMIT_RANGE="$LAST_MERGE..HEAD"
+ # make sure it works now
+ if ! git rev-list $COMMIT_RANGE >/dev/null; then
+ COMMIT_RANGE=""
+ fi
+ echo $COMMIT_RANGE
+}
+
+COMMIT_RANGE_FROM_LAST_MERGE=$(get_commit_range_from_last_merge)
+
+if [ -n "$TRAVIS" ]; then
+ CI_COMMIT=$TRAVIS_COMMIT
+ CI_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE/.../..}"
+ CI_BRANCH=$TRAVIS_BRANCH
+ CI_EVENT_TYPE=$TRAVIS_EVENT_TYPE
+ CI_REPO_SLUG=$TRAVIS_REPO_SLUG
+
+ # CI_COMMIT_RANGE is usually invalid for force pushes - fix it when used
+ # with non-upstream repository
+ if [ -n "$CI_COMMIT_RANGE" -a "$CI_REPO_SLUG" != "$GITHUB_REPO" ]; then
+ if ! git rev-list $CI_COMMIT_RANGE; then
+ CI_COMMIT_RANGE=$COMMIT_RANGE_FROM_LAST_MERGE
+ fi
+ fi
+
+ case "$TRAVIS_CPU_ARCH" in
+ "amd64")
+ CI_CPU_ARCH="x86_64"
+ ;;
+ *)
+ CI_CPU_ARCH=$TRAVIS_CPU_ARCH
+ ;;
+ esac
+
+elif [ -n "$GITHUB_ACTIONS" ]; then
+ CI_COMMIT=$GITHUB_SHA
+ CI_COMMIT_RANGE=$COMMIT_RANGE_FROM_LAST_MERGE
+ CI_BRANCH=$(echo $GITHUB_REF | cut -d'/' -f3)
+ CI_REPO_SLUG=$GITHUB_REPOSITORY
+ CI_CPU_ARCH="x86_64" # GitHub Actions supports only x86_64
+
+ case "$GITHUB_EVENT_NAME" in
+ "schedule")
+ CI_EVENT_TYPE="cron"
+ ;;
+ *)
+ CI_EVENT_TYPE=$GITHUB_EVENT_NAME
+ ;;
+ esac
+
+else
+ CI_COMMIT=$(git log --pretty=%H -1)
+ CI_COMMIT_RANGE=$COMMIT_RANGE_FROM_LAST_MERGE
+ CI_CPU_ARCH="x86_64"
+fi
+
+export CI_COMMIT=$CI_COMMIT
+export CI_COMMIT_RANGE=$CI_COMMIT_RANGE
+export CI_BRANCH=$CI_BRANCH
+export CI_EVENT_TYPE=$CI_EVENT_TYPE
+export CI_REPO_SLUG=$CI_REPO_SLUG
+export CI_CPU_ARCH=$CI_CPU_ARCH
+
+echo CI_COMMIT=$CI_COMMIT
+echo CI_COMMIT_RANGE=$CI_COMMIT_RANGE
+echo CI_BRANCH=$CI_BRANCH
+echo CI_EVENT_TYPE=$CI_EVENT_TYPE
+echo CI_REPO_SLUG=$CI_REPO_SLUG
+echo CI_CPU_ARCH=$CI_CPU_ARCH
diff --git a/src/pmdk/utils/docker/set-vars.sh b/src/pmdk/utils/docker/set-vars.sh
new file mode 100755
index 000000000..9a531a840
--- /dev/null
+++ b/src/pmdk/utils/docker/set-vars.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019, Intel Corporation
+
+#
+# set-vars.sh - set required environment variables
+#
+
+set -e
+
+export CI_FILE_PUSH_IMAGE_TO_REPO=/tmp/push_image_to_repo_flag
+export CI_FILE_SKIP_BUILD_PKG_CHECK=/tmp/skip_build_package_check
diff --git a/src/pmdk/utils/docker/test_package/.gitignore b/src/pmdk/utils/docker/test_package/.gitignore
new file mode 100644
index 000000000..7e564dc4e
--- /dev/null
+++ b/src/pmdk/utils/docker/test_package/.gitignore
@@ -0,0 +1 @@
+test_package
diff --git a/src/pmdk/utils/docker/test_package/Makefile b/src/pmdk/utils/docker/test_package/Makefile
new file mode 100644
index 000000000..f5970aac3
--- /dev/null
+++ b/src/pmdk/utils/docker/test_package/Makefile
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2018, Intel Corporation
+
+check_package = $(shell pkg-config $(1) && echo y || echo n)
+
+HAS_LIBPMEMOBJ := $(call check_package, libpmemobj --atleast-version $(LIBPMEMOBJ_MIN_VERSION) --print-errors)
+
+LIBS += $(shell pkg-config --libs libpmemobj)
+CFLAGS += $(shell pkg-config --cflags libpmemobj)
+
+ifeq ($(HAS_LIBPMEMOBJ),n)
+$(error libpmemobj(version >= $(LIBPMEMOBJ_MIN_VERSION)) is missing)
+endif
+
+test_package: test_package.c
+ $(CC) test_package.c $(LIBS) $(CFLAGS) -o $@
+
+clean:
+ rm -f test_package
+
+.PHONY: clean
diff --git a/src/pmdk/utils/docker/test_package/README b/src/pmdk/utils/docker/test_package/README
new file mode 100644
index 000000000..de81a6a5b
--- /dev/null
+++ b/src/pmdk/utils/docker/test_package/README
@@ -0,0 +1,6 @@
+Persistent Memory Development Kit
+
+This is utils/docker/test_package/README.
+
+This directory contains simple application which uses libpmemobj.
+It can be used to test whether libpmemobj was installed properly.
diff --git a/src/pmdk/utils/docker/test_package/test_package.c b/src/pmdk/utils/docker/test_package/test_package.c
new file mode 100644
index 000000000..cf1e7eb8b
--- /dev/null
+++ b/src/pmdk/utils/docker/test_package/test_package.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* Copyright 2018, Intel Corporation */
+
+#include <libpmemobj.h>
+#include <stdio.h>
+#include <sys/stat.h>
+
+#define LAYOUT_NAME "test"
+
+struct my_root {
+ int foo;
+};
+
+int
+main(int argc, char *argv[])
+{
+ if (argc < 2) {
+ printf("usage: %s file-name\n", argv[0]);
+ return 1;
+ }
+
+ const char *path = argv[1];
+
+ PMEMobjpool *pop = pmemobj_create(path, LAYOUT_NAME,
+ PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR);
+
+ if (pop == NULL) {
+ printf("failed to create pool\n");
+ return 1;
+ }
+
+ PMEMoid root = pmemobj_root(pop, sizeof(struct my_root));
+ struct my_root *rootp = pmemobj_direct(root);
+
+ rootp->foo = 10;
+ pmemobj_persist(pop, &rootp->foo, sizeof(rootp->foo));
+
+ pmemobj_close(pop);
+
+ return 0;
+}
diff --git a/src/pmdk/utils/docker/valid-branches.sh b/src/pmdk/utils/docker/valid-branches.sh
new file mode 100755
index 000000000..b111c2a3d
--- /dev/null
+++ b/src/pmdk/utils/docker/valid-branches.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2018-2020, Intel Corporation
+
+declare -A TARGET_BRANCHES=( \
+ ["master"]="master" \
+ ["stable-1.5"]="v1.5" \
+ ["stable-1.6"]="v1.6" \
+ ["stable-1.7"]="v1.7" \
+ ["stable-1.8"]="v1.8" \
+ ["stable-1.9"]="v1.9" \
+ )
diff --git a/src/pmdk/utils/get_aliases.sh b/src/pmdk/utils/get_aliases.sh
new file mode 100755
index 000000000..87978e2bc
--- /dev/null
+++ b/src/pmdk/utils/get_aliases.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2020, Intel Corporation
+#
+
+#
+# get_aliases.sh -- generate map of manuals functions and libraries
+#
+# usage: run from /pmdk/doc/generated location without parameters:
+# ./../../utils/get_aliases.sh
+#
+# This script searches manpages from section 7 then
+# takes all functions from each section using specified pattern
+# and at the end to every function it assign real markdown file
+# representation based on *.gz file content
+#
+# Generated libs_map.yml file is used on gh-pages
+# to handle functions and their aliases
+#
+
+list=("$@")
+man_child=("$@")
+
+function search_aliases {
+children=$1
+parent=$2
+for i in ${children[@]}
+do
+ if [ -e ../$parent/$i ]
+ then
+ echo "Man: $i"
+ content=$(head -c 150 ../$parent/$i)
+ if [[ "$content" == ".so "* ]] ;
+ then
+ content=$(basename ${content#".so"})
+ i="${i%.*}"
+ echo " $i: $content" >> $map_file
+ else
+ r="${i%.*}"
+ echo " $r: $i" >> $map_file
+ fi
+ fi
+done
+}
+
+function list_pages {
+ parent="${1%.*}"
+ list=("$@")
+ man_child=("$@")
+
+ if [ "$parent" == "libpmem" ]; then
+ man_child=($(ls -1 ../libpmem | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "libpmem2" ]; then
+ man_child=($(ls -1 ../libpmem2 | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "libpmemblk" ]; then
+ man_child=($(ls -1 ../libpmemblk | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "libpmemlog" ]; then
+ man_child=($(ls -1 ../libpmemlog | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "libpmemobj" ]; then
+ man_child=($(ls -1 ../libpmemobj | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "libpmempool" ]; then
+ man_child=($(ls -1 ../libpmempool | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ "$parent" == "librpmem" ]; then
+ man_child=($(ls -1 ../librpmem | grep -e ".*\.3$"))
+ echo -n "- $parent: " >> $map_file
+ echo "${man_child[@]}" >> $map_file
+ fi
+
+ if [ ${#man_child[@]} -ne 0 ]
+ then
+ list=${man_child[@]}
+ search_aliases "${list[@]}" "$parent"
+ fi
+}
+
+man7=($(ls -1 ../*/ | grep -e ".*\.7$"))
+
+map_file=libs_map.yml
+[ -e $map_file ] && rm $map_file
+touch $map_file
+
+for i in "${man7[@]}"
+do
+echo "Library: $i"
+ list_pages $i
+done
diff --git a/src/pmdk/utils/git-years b/src/pmdk/utils/git-years
new file mode 100755
index 000000000..d54018ddf
--- /dev/null
+++ b/src/pmdk/utils/git-years
@@ -0,0 +1,8 @@
+#!/bin/sh
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2019, Intel Corporation
+
+# git-years -- calculate the range of years for a given file from git
+
+git log --pretty='%aI %aE' "$@"|grep '@intel\.com'|cut -d- -f1|sort|
+ sed '$p;2,$d'|uniq|tr '\n' -|sed 's/-$//'
diff --git a/src/pmdk/utils/libpmem.pc.in b/src/pmdk/utils/libpmem.pc.in
new file mode 100644
index 000000000..850b28198
--- /dev/null
+++ b/src/pmdk/utils/libpmem.pc.in
@@ -0,0 +1,9 @@
+includedir=${prefix}/include
+
+Name: libpmem
+Description: libpmem library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires:
+Libs: -L${libdir} -lpmem
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/libpmem2.pc.in b/src/pmdk/utils/libpmem2.pc.in
new file mode 100644
index 000000000..d4ddc907c
--- /dev/null
+++ b/src/pmdk/utils/libpmem2.pc.in
@@ -0,0 +1,9 @@
+includedir=${prefix}/include
+
+Name: libpmem2
+Description: libpmem2 library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires:
+Libs: -L${libdir} -lpmem2
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/libpmemblk.pc.in b/src/pmdk/utils/libpmemblk.pc.in
new file mode 100644
index 000000000..5b0ffbf3e
--- /dev/null
+++ b/src/pmdk/utils/libpmemblk.pc.in
@@ -0,0 +1,9 @@
+includedir=${prefix}/include
+
+Name: libpmemblk
+Description: libpmemblk library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires.private: libpmem${rasdeps}
+Libs: -L${libdir} -lpmemblk
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/libpmemlog.pc.in b/src/pmdk/utils/libpmemlog.pc.in
new file mode 100644
index 000000000..f1658438b
--- /dev/null
+++ b/src/pmdk/utils/libpmemlog.pc.in
@@ -0,0 +1,9 @@
+includedir=${prefix}/include
+
+Name: libpmemlog
+Description: libpmemlog library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires.private: libpmem${rasdeps}
+Libs: -L${libdir} -lpmemlog
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/libpmemobj.pc.in b/src/pmdk/utils/libpmemobj.pc.in
new file mode 100644
index 000000000..12c396e9e
--- /dev/null
+++ b/src/pmdk/utils/libpmemobj.pc.in
@@ -0,0 +1,10 @@
+includedir=${prefix}/include
+
+Name: libpmemobj
+Description: libpmemobj library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires.private: libpmem${rasdeps}
+Libs: -L${libdir} -lpmemobj
+Libs.private: -ldl
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/libpmempool.pc.in b/src/pmdk/utils/libpmempool.pc.in
new file mode 100644
index 000000000..660938a27
--- /dev/null
+++ b/src/pmdk/utils/libpmempool.pc.in
@@ -0,0 +1,10 @@
+includedir=${prefix}/include
+
+Name: libpmempool
+Description: libpmempool library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires.private: libpmem${rasdeps}
+Libs: -L${libdir} -lpmempool
+Libs.private: -ldl
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/librpmem.pc.in b/src/pmdk/utils/librpmem.pc.in
new file mode 100644
index 000000000..50bf1bb91
--- /dev/null
+++ b/src/pmdk/utils/librpmem.pc.in
@@ -0,0 +1,9 @@
+includedir=${prefix}/include
+
+Name: librpmem
+Description: librpmem library from PMDK project
+Version: ${version}
+URL: https://pmem.io/pmdk
+Requires:
+Libs: -L${libdir} -lrpmem
+Cflags: -I${includedir}
diff --git a/src/pmdk/utils/magic-install.sh b/src/pmdk/utils/magic-install.sh
new file mode 100644
index 000000000..3c65bab49
--- /dev/null
+++ b/src/pmdk/utils/magic-install.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2017, Intel Corporation
+#
+# magic-install.sh -- Script for installing magic script
+#
+set -e
+
+if ! grep -q "File: pmdk" /etc/magic
+then
+ echo "Appending PMDK magic to /etc/magic"
+ cat /usr/share/pmdk/pmdk.magic >> /etc/magic
+else
+ echo "PMDK magic already exists"
+fi
diff --git a/src/pmdk/utils/magic-uninstall.sh b/src/pmdk/utils/magic-uninstall.sh
new file mode 100644
index 000000000..6733c7e72
--- /dev/null
+++ b/src/pmdk/utils/magic-uninstall.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2017, Intel Corporation
+#
+# magic-uninstall.sh -- Script for uninstalling magic script
+#
+set -e
+
+HDR_LOCAL=$(grep "File: pmdk" /etc/magic)
+HDR_PKG=$(grep "File: pmdk" /usr/share/pmdk/pmdk.magic)
+
+if [[ $HDR_LOCAL == $HDR_PKG ]]
+then
+ echo "Removing PMDK magic from /etc/magic"
+ HDR_LINE=$(grep -n "File: pmdk" /etc/magic | cut -f1 -d:)
+ HDR_PKG_LINE=$(grep -n "File: pmdk" /usr/share/pmdk/pmdk.magic | cut -f1 -d:)
+ HDR_LINES=$(cat /usr/share/pmdk/pmdk.magic | wc -l)
+ HDR_FIRST=$(($HDR_LINE - $HDR_PKG_LINE + 1))
+ HDR_LAST=$(($HDR_FIRST + $HDR_LINES))
+ sed -i "${HDR_FIRST},${HDR_LAST}d" /etc/magic
+fi
diff --git a/src/pmdk/utils/md2man.sh b/src/pmdk/utils/md2man.sh
new file mode 100755
index 000000000..941bd3c96
--- /dev/null
+++ b/src/pmdk/utils/md2man.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+#
+
+#
+# md2man.sh -- convert markdown to groff man pages
+#
+# usage: md2man.sh file template outfile
+#
+# This script converts markdown file into groff man page using pandoc.
+# It performs some pre- and post-processing for better results:
+# - uses m4 to preprocess OS-specific directives. See doc/macros.man.
+# - parse input file for YAML metadata block and read man page title,
+# section and version
+# - cut-off metadata block and license
+# - unindent code blocks
+# - cut-off windows and web specific parts of documentation
+#
+# If the TESTOPTS variable is set, generates a preprocessed markdown file
+# with the header stripped off for testing purposes.
+#
+
+set -e
+set -o pipefail
+
+filename=$1
+template=$2
+outfile=$3
+title=`sed -n 's/^title:\ _MP(*\([A-Za-z0-9_-]*\).*$/\1/p' $filename`
+section=`sed -n 's/^title:.*\([0-9]\))$/\1/p' $filename`
+version=`sed -n 's/^date:\ *\(.*\)$/\1/p' $filename`
+
+if [ "$TESTOPTS" != "" ]; then
+ m4 $TESTOPTS macros.man $filename | sed -n -e '/# NAME #/,$p' > $outfile
+else
+ OPTS=
+
+if [ "$WIN32" == 1 ]; then
+ OPTS="$OPTS -DWIN32"
+else
+ OPTS="$OPTS -UWIN32"
+fi
+
+if [ "$(uname -s)" == "FreeBSD" ]; then
+ OPTS="$OPTS -DFREEBSD"
+else
+ OPTS="$OPTS -UFREEBSD"
+fi
+
+if [ "$WEB" == 1 ]; then
+ OPTS="$OPTS -DWEB"
+ mkdir -p "$(dirname $outfile)"
+ m4 $OPTS macros.man $filename | sed -n -e '/---/,$p' > $outfile
+else
+ SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date +%s)}"
+ COPYRIGHT=$(grep -rwI "\[comment]: <> (Copyright" $filename |\
+ sed "s/\[comment\]: <> (\([^)]*\))/\1/")
+ dt=$(date -u -d "@$SOURCE_DATE_EPOCH" +%F 2>/dev/null ||
+ date -u -r "$SOURCE_DATE_EPOCH" +%F 2>/dev/null || date -u +%F)
+ m4 $OPTS macros.man $filename | sed -n -e '/# NAME #/,$p' |\
+ pandoc -s -t man -o $outfile --template=$template \
+ -V title=$title -V section=$section \
+ -V date="$dt" -V version="$version" \
+ -V copyright="$COPYRIGHT"
+fi
+fi
diff --git a/src/pmdk/utils/os-banned b/src/pmdk/utils/os-banned
new file mode 100644
index 000000000..57d162551
--- /dev/null
+++ b/src/pmdk/utils/os-banned
@@ -0,0 +1,63 @@
+pthread_once
+pthread_key_create
+pthread_key_delete
+pthread_setspecific
+pthread_getspecific
+pthread_mutex_init
+pthread_mutex_destroy
+pthread_mutex_lock
+pthread_mutex_trylock
+pthread_mutex_unlock
+pthread_mutex_timedlock
+pthread_rwlock_init
+pthread_rwlock_destroy
+pthread_rwlock_rdlock
+pthread_rwlock_wrlock
+pthread_rwlock_tryrdlock
+pthread_rwlock_trywrlock
+pthread_rwlock_unlock
+pthread_rwlock_timedrdlock
+pthread_rwlock_timedwrlock
+pthread_spin_init
+pthread_spin_destroy
+pthread_spin_lock
+pthread_spin_unlock
+pthread_spin_trylock
+pthread_cond_init
+pthread_cond_destroy
+pthread_cond_broadcast
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_create
+pthread_join
+cpu_zero
+cpu_set
+pthread_setaffinity_np
+pthread_atfork
+sem_init
+sem_destroy
+sem_wait
+sem_trywait
+sem_post
+fsync
+fsync_dir
+open
+stat
+unlink
+access
+fopen
+fdopen
+chmod
+mkstemp
+posix_fallocate
+ftruncate
+flock
+writev
+clock_gettime
+rand_r
+unsetenv
+setenv
+getenv
+strsignal
+execv
diff --git a/src/pmdk/utils/pkg-common.sh b/src/pmdk/utils/pkg-common.sh
new file mode 100644
index 000000000..f3711bc59
--- /dev/null
+++ b/src/pmdk/utils/pkg-common.sh
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2019, Intel Corporation
+
+#
+# pkg-common.sh - common functions and variables for building packages
+#
+
+export LC_ALL="C"
+
+function error() {
+ echo -e "error: $@"
+}
+
+function check_dir() {
+ if [ ! -d $1 ]
+ then
+ error "Directory '$1' does not exist."
+ exit 1
+ fi
+}
+
+function check_file() {
+ if [ ! -f $1 ]
+ then
+ error "File '$1' does not exist."
+ exit 1
+ fi
+}
+
+function check_tool() {
+ local tool=$1
+ if [ -z "$(which $tool 2>/dev/null)" ]
+ then
+ error "'${tool}' not installed or not in PATH"
+ exit 1
+ fi
+}
+
+function get_version() {
+ echo -n $1 | sed "s/-rc/~rc/"
+}
+
+function get_os() {
+ if [ -f /etc/os-release ]
+ then
+ local OS=$(cat /etc/os-release | grep -m1 -o -P '(?<=NAME=).*($)')
+ [[ "$OS" =~ SLES|openSUSE ]] && echo -n "SLES_like" ||
+ ([[ "$OS" =~ "Fedora"|"Red Hat"|"CentOS" ]] && echo -n "RHEL_like" || echo 1)
+ else
+ echo 1
+ fi
+}
+
+REGEX_DATE_AUTHOR="([a-zA-Z]{3} [a-zA-Z]{3} [0-9]{2} [0-9]{4})\s*(.*)"
+REGEX_MESSAGE_START="\s*\*\s*(.*)"
+REGEX_MESSAGE="\s*(\S.*)"
diff --git a/src/pmdk/utils/pkg-config.sh b/src/pmdk/utils/pkg-config.sh
new file mode 100644
index 000000000..7186fa2ee
--- /dev/null
+++ b/src/pmdk/utils/pkg-config.sh
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2014-2020, Intel Corporation
+
+# Name of package
+PACKAGE_NAME="pmdk"
+
+# Name and email of package maintainer
+PACKAGE_MAINTAINER="Piotr Balcer <piotr.balcer@intel.com>"
+
+# Brief description of the package
+PACKAGE_SUMMARY="Persistent Memory Development Kit"
+
+# Full description of the package
+PACKAGE_DESCRIPTION="The collection of libraries and utilities for Persistent Memory Programming"
+
+# Website
+PACKAGE_URL="https://pmem.io/pmdk"
diff --git a/src/pmdk/utils/pmdk.magic b/src/pmdk/utils/pmdk.magic
new file mode 100644
index 000000000..7409ba1ef
--- /dev/null
+++ b/src/pmdk/utils/pmdk.magic
@@ -0,0 +1,15 @@
+
+#------------------------------------------------------------------------------
+# $File: pmdk,v 1.2 2017/12/11 20:00:00
+# pmdk: file(1) magic for Persistent Memory Development Kit pool files
+#
+# The PMDK specific format of pool files.
+#
+# PMEM signature
+0 string PMEM
+>4 string POOLSET Persistent Memory Poolset file
+>>11 search REPLICA with replica
+# Pool type signature
+>4 regex LOG|BLK|OBJ Persistent Memory Pool file, type: %s,
+# Major version number
+>>8 lelong >0 version 0x%x
diff --git a/src/pmdk/utils/pmdk.spec.in b/src/pmdk/utils/pmdk.spec.in
new file mode 100644
index 000000000..094e9d0b4
--- /dev/null
+++ b/src/pmdk/utils/pmdk.spec.in
@@ -0,0 +1,710 @@
+
+# rpmbuild options:
+# --with | --without fabric
+# --with | --without ndctl
+# --define _testconfig <path to custom testconfig.sh>
+# --define _skip_check 1
+
+# do not terminate build if files in the $RPM_BUILD_ROOT
+# directory are not found in the %files (without rpmem case)
+%define _unpackaged_files_terminate_build 0
+
+# disable 'make check' on suse
+%if %{defined suse_version}
+ %define _skip_check 1
+ %define dist .suse%{suse_version}
+%endif
+
+# libfabric v1.4.2 is available on:
+# openSUSE Tumbleweed, Leap 15.0, Leap 42.3; SLE 12 SP3, 15
+# Fedora >=27; RHEL >=7.5
+%if (0%{?suse_version} > 1315) || (0%{?fedora} >= 27) || (0%{?rhel} >= 7)
+%bcond_without fabric
+%else
+%bcond_with fabric
+%endif
+
+%bcond_without ndctl
+
+%define min_libfabric_ver __LIBFABRIC_MIN_VER__
+%define min_ndctl_ver __NDCTL_MIN_VER__
+
+Name: pmdk
+Version: __VERSION__
+Release: 1%{?dist}
+Summary: __PACKAGE_SUMMARY__
+Packager: __PACKAGE_MAINTAINER__
+Group: __GROUP_SYS_LIBS__
+License: __LICENSE__
+URL: https://pmem.io/pmdk
+
+Source0: %{name}-%{version}.tar.gz
+
+BuildRequires: gcc
+BuildRequires: make
+BuildRequires: glibc-devel
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: man
+BuildRequires: pkgconfig
+BuildRequires: gdb
+
+# fdupes package is available only on 'openSUSE Tumbleweed' and 'openSUSE Leap 15.1'
+%if (0%{?suse_version} > 1500) || (0%{?sles_version} >= 150100 && 0%{?is_opensuse})
+BuildRequires: fdupes
+%endif
+
+%if %{with ndctl}
+%if %{defined suse_version}
+BuildRequires: libndctl-devel >= %{min_ndctl_ver}
+%else
+BuildRequires: ndctl-devel >= %{min_ndctl_ver}
+BuildRequires: daxctl-devel >= %{min_ndctl_ver}
+%endif
+%endif
+
+%if %{with fabric}
+BuildRequires: libfabric-devel >= %{min_libfabric_ver}
+%endif
+
+
+# Debug variants of the libraries should be filtered out of the provides.
+%global __provides_exclude_from ^%{_libdir}/pmdk_debug/.*\\.so.*$
+
+# By design, PMDK does not support any 32-bit architecture.
+# Due to dependency on xmmintrin.h and some inline assembly, it can be
+# compiled only for x86_64 at the moment.
+# Other 64-bit architectures could also be supported, if only there is
+# a request for that, and if somebody provides the arch-specific
+# implementation of the low-level routines for flushing to persistent
+# memory.
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=1340634
+# https://bugzilla.redhat.com/show_bug.cgi?id=1340635
+# https://bugzilla.redhat.com/show_bug.cgi?id=1340636
+# https://bugzilla.redhat.com/show_bug.cgi?id=1340637
+
+ExclusiveArch: x86_64 ppc64le
+
+%description
+The Persistent Memory Development Kit is a collection of libraries for
+using memory-mapped persistence, optimized specifically for persistent memory.
+
+
+%package -n libpmem2__PKG_NAME_SUFFIX__
+Summary: Low-level persistent memory support library
+Group: __GROUP_SYS_LIBS__
+%description -n libpmem2__PKG_NAME_SUFFIX__
+The libpmem2 provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+%files -n libpmem2__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%dir %{_datadir}/pmdk
+%{_libdir}/libpmem2.so.*
+%{_datadir}/pmdk/pmdk.magic
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmem2-devel
+Summary: Development files for the low-level persistent memory library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmem2__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmem2-devel
+The libpmem2 provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+This library is provided for software which tracks every store to
+pmem and needs to flush those changes to durability. Most developers
+will find higher level libraries like libpmemobj to be much more
+convenient.
+
+%files -n libpmem2-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmem2.so
+%{_libdir}/pkgconfig/libpmem2.pc
+%{_includedir}/libpmem2.h
+%{_mandir}/man7/libpmem2.7.gz
+%{_mandir}/man3/pmem2_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmem2-debug
+Summary: Debug variant of the low-level persistent memory library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmem2__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmem2-debug
+The libpmem provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmem2-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmem2.so
+%{_libdir}/pmdk_debug/libpmem2.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+
+%package -n libpmem__PKG_NAME_SUFFIX__
+Summary: Low-level persistent memory support library
+Group: __GROUP_SYS_LIBS__
+%description -n libpmem__PKG_NAME_SUFFIX__
+The libpmem provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+%files -n libpmem__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%dir %{_datadir}/pmdk
+%{_libdir}/libpmem.so.*
+%{_datadir}/pmdk/pmdk.magic
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmem-devel
+Summary: Development files for the low-level persistent memory library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmem-devel
+The libpmem provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+This library is provided for software which tracks every store to
+pmem and needs to flush those changes to durability. Most developers
+will find higher level libraries like libpmemobj to be much more
+convenient.
+
+%files -n libpmem-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmem.so
+%{_libdir}/pkgconfig/libpmem.pc
+%{_includedir}/libpmem.h
+%{_mandir}/man7/libpmem.7.gz
+%{_mandir}/man3/pmem_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmem-debug
+Summary: Debug variant of the low-level persistent memory library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmem-debug
+The libpmem provides low level persistent memory support. In particular,
+support for the persistent memory instructions for flushing changes
+to pmem is provided.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmem-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmem.so
+%{_libdir}/pmdk_debug/libpmem.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemblk__PKG_NAME_SUFFIX__
+Summary: Persistent Memory Resident Array of Blocks library
+Group: __GROUP_SYS_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+%description -n libpmemblk__PKG_NAME_SUFFIX__
+The libpmemblk implements a pmem-resident array of blocks, all the same
+size, where a block is updated atomically with respect to power
+failure or program interruption (no torn blocks).
+
+%files -n libpmemblk__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%{_libdir}/libpmemblk.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemblk-devel
+Summary: Development files for the Persistent Memory Resident Array of Blocks library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemblk__PKG_NAME_SUFFIX__ = %{version}-%{release}
+Requires: libpmem-devel = %{version}-%{release}
+%description -n libpmemblk-devel
+The libpmemblk implements a pmem-resident array of blocks, all the same
+size, where a block is updated atomically with respect to power
+failure or program interruption (no torn blocks).
+
+For example, a program keeping a cache of fixed-size objects in pmem
+might find this library useful. This library is provided for cases
+requiring large arrays of objects at least 512 bytes each. Most
+developers will find higher level libraries like libpmemobj to be
+more generally useful.
+
+%files -n libpmemblk-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmemblk.so
+%{_libdir}/pkgconfig/libpmemblk.pc
+%{_includedir}/libpmemblk.h
+%{_mandir}/man7/libpmemblk.7.gz
+%{_mandir}/man5/poolset.5.gz
+%{_mandir}/man3/pmemblk_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemblk-debug
+Summary: Debug variant of the Persistent Memory Resident Array of Blocks library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemblk__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmemblk-debug
+The libpmemblk implements a pmem-resident array of blocks, all the same
+size, where a block is updated atomically with respect to power
+failure or program interruption (no torn blocks).
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmemblk-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmemblk.so
+%{_libdir}/pmdk_debug/libpmemblk.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemlog__PKG_NAME_SUFFIX__
+Summary: Persistent Memory Resident Log File library
+Group: __GROUP_SYS_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+%description -n libpmemlog__PKG_NAME_SUFFIX__
+The libpmemlog library provides a pmem-resident log file. This is
+useful for programs like databases that append frequently to a log
+file.
+
+%files -n libpmemlog__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%{_libdir}/libpmemlog.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemlog-devel
+Summary: Development files for the Persistent Memory Resident Log File library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemlog__PKG_NAME_SUFFIX__ = %{version}-%{release}
+Requires: libpmem-devel = %{version}-%{release}
+%description -n libpmemlog-devel
+The libpmemlog library provides a pmem-resident log file. This
+library is provided for cases requiring an append-mostly file to
+record variable length entries. Most developers will find higher
+level libraries like libpmemobj to be more generally useful.
+
+%files -n libpmemlog-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmemlog.so
+%{_libdir}/pkgconfig/libpmemlog.pc
+%{_includedir}/libpmemlog.h
+%{_mandir}/man7/libpmemlog.7.gz
+%{_mandir}/man5/poolset.5.gz
+%{_mandir}/man3/pmemlog_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemlog-debug
+Summary: Debug variant of the Persistent Memory Resident Log File library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemlog__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmemlog-debug
+The libpmemlog library provides a pmem-resident log file. This
+library is provided for cases requiring an append-mostly file to
+record variable length entries. Most developers will find higher
+level libraries like libpmemobj to be more generally useful.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmemlog-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmemlog.so
+%{_libdir}/pmdk_debug/libpmemlog.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemobj__PKG_NAME_SUFFIX__
+Summary: Persistent Memory Transactional Object Store library
+Group: __GROUP_SYS_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+%description -n libpmemobj__PKG_NAME_SUFFIX__
+The libpmemobj library provides a transactional object store,
+providing memory allocation, transactions, and general facilities for
+persistent memory programming.
+
+%files -n libpmemobj__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%{_libdir}/libpmemobj.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemobj-devel
+Summary: Development files for the Persistent Memory Transactional Object Store library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemobj__PKG_NAME_SUFFIX__ = %{version}-%{release}
+Requires: libpmem-devel = %{version}-%{release}
+%description -n libpmemobj-devel
+The libpmemobj library provides a transactional object store,
+providing memory allocation, transactions, and general facilities for
+persistent memory programming. Developers new to persistent memory
+probably want to start with this library.
+
+%files -n libpmemobj-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmemobj.so
+%{_libdir}/pkgconfig/libpmemobj.pc
+%{_includedir}/libpmemobj.h
+%{_includedir}/libpmemobj/*.h
+%{_mandir}/man7/libpmemobj.7.gz
+%{_mandir}/man5/poolset.5.gz
+%{_mandir}/man3/pmemobj_*.3.gz
+%{_mandir}/man3/pobj_*.3.gz
+%{_mandir}/man3/oid_*.3.gz
+%{_mandir}/man3/toid*.3.gz
+%{_mandir}/man3/direct_*.3.gz
+%{_mandir}/man3/d_r*.3.gz
+%{_mandir}/man3/tx_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmemobj-debug
+Summary: Debug variant of the Persistent Memory Transactional Object Store library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmemobj__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmemobj-debug
+The libpmemobj library provides a transactional object store,
+providing memory allocation, transactions, and general facilities for
+persistent memory programming. Developers new to persistent memory
+probably want to start with this library.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmemobj-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmemobj.so
+%{_libdir}/pmdk_debug/libpmemobj.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmempool__PKG_NAME_SUFFIX__
+Summary: Persistent Memory pool management library
+Group: __GROUP_SYS_LIBS__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+%description -n libpmempool__PKG_NAME_SUFFIX__
+The libpmempool library provides a set of utilities for off-line
+administration, analysis, diagnostics and repair of persistent memory
+pools created by libpmemlog, libpemblk and libpmemobj libraries.
+
+%files -n libpmempool__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%{_libdir}/libpmempool.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmempool-devel
+Summary: Development files for Persistent Memory pool management library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmempool__PKG_NAME_SUFFIX__ = %{version}-%{release}
+Requires: libpmem-devel = %{version}-%{release}
+%description -n libpmempool-devel
+The libpmempool library provides a set of utilities for off-line
+administration, analysis, diagnostics and repair of persistent memory
+pools created by libpmemlog, libpemblk and libpmemobj libraries.
+
+%files -n libpmempool-devel
+%defattr(-,root,root,-)
+%{_libdir}/libpmempool.so
+%{_libdir}/pkgconfig/libpmempool.pc
+%{_includedir}/libpmempool.h
+%{_mandir}/man7/libpmempool.7.gz
+%{_mandir}/man5/poolset.5.gz
+%{_mandir}/man3/pmempool_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n libpmempool-debug
+Summary: Debug variant of the Persistent Memory pool management library
+Group: __GROUP_DEV_LIBS__
+Requires: libpmempool__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n libpmempool-debug
+The libpmempool library provides a set of utilities for off-line
+administration, analysis, diagnostics and repair of persistent memory
+pools created by libpmemlog, libpemblk and libpmemobj libraries.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n libpmempool-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/libpmempool.so
+%{_libdir}/pmdk_debug/libpmempool.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%if %{with fabric}
+
+%package -n librpmem__PKG_NAME_SUFFIX__
+Summary: Remote Access to Persistent Memory library
+Group: __GROUP_SYS_LIBS__
+Requires: libfabric >= %{min_libfabric_ver}
+%if %{defined suse_version}
+Requires: openssh
+%else
+Requires: openssh-clients
+%endif
+%description -n librpmem__PKG_NAME_SUFFIX__
+The librpmem library provides low-level support for remote access
+to persistent memory utilizing RDMA-capable NICs. It can be used
+to replicate persistent memory regions over RDMA protocol.
+
+%files -n librpmem__PKG_NAME_SUFFIX__
+%defattr(-,root,root,-)
+%{_libdir}/librpmem.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n librpmem-devel
+Summary: Development files for the Remote Access to Persistent Memory library
+Group: __GROUP_DEV_LIBS__
+Requires: librpmem__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n librpmem-devel
+The librpmem library provides low-level support for remote access
+to persistent memory utilizing RDMA-capable NICs. It can be used
+to replicate persistent memory regions over RDMA protocol.
+
+This sub-package contains libraries and header files for developing
+applications that want to specifically make use of librpmem.
+
+%files -n librpmem-devel
+%defattr(-,root,root,-)
+%{_libdir}/librpmem.so
+%{_libdir}/pkgconfig/librpmem.pc
+%{_includedir}/librpmem.h
+%{_mandir}/man7/librpmem.7.gz
+%{_mandir}/man3/rpmem_*.3.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n librpmem-debug
+Summary: Debug variant of the Remote Access to Persistent Memory library
+Group: __GROUP_DEV_LIBS__
+Requires: librpmem__PKG_NAME_SUFFIX__ = %{version}-%{release}
+%description -n librpmem-debug
+The librpmem library provides low-level support for remote access
+to persistent memory utilizing RDMA-capable NICs. It can be used
+to replicate persistent memory regions over RDMA protocol.
+
+This sub-package contains debug variant of the library, providing
+run-time assertions and trace points. The typical way to access the
+debug version is to set the environment variable LD_LIBRARY_PATH to
+/usr/lib64/pmdk_debug.
+
+%files -n librpmem-debug
+%defattr(-,root,root,-)
+%dir %{_libdir}/pmdk_debug
+%{_libdir}/pmdk_debug/librpmem.so
+%{_libdir}/pmdk_debug/librpmem.so.*
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%package -n rpmemd
+Group: __GROUP_SYS_BASE__
+Summary: Target node process executed by librpmem
+Requires: libfabric >= %{min_libfabric_ver}
+%description -n rpmemd
+The rpmemd process is executed on a target node by librpmem library
+and facilitates access to persistent memory over RDMA.
+
+%files -n rpmemd
+%{_bindir}/rpmemd
+%{_mandir}/man1/rpmemd.1.gz
+
+# end of "if _with_fabric"
+%endif
+
+%package -n pmempool
+Summary: Utilities for Persistent Memory
+Group: __GROUP_SYS_BASE__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+Requires: libpmemlog__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+Requires: libpmemblk__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+Requires: libpmemobj__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+Requires: libpmempool__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+Obsoletes: nvml-tools < %{version}-%{release}
+%description -n pmempool
+The pmempool is a standalone utility for management and off-line analysis
+of Persistent Memory pools created by PMDK libraries. It provides a set
+of utilities for administration and diagnostics of Persistent Memory pools.
+The pmempool may be useful for troubleshooting by system administrators
+and users of the applications based on PMDK libraries.
+
+%files -n pmempool
+%{_bindir}/pmempool
+%{_mandir}/man1/pmempool.1.gz
+%{_mandir}/man1/pmempool-*.1.gz
+%config(noreplace) %{_sysconfdir}/bash_completion.d/pmempool
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+%package -n pmreorder
+Summary: Consistency Checker for Persistent Memory
+Group: __GROUP_SYS_BASE__
+%description -n pmreorder
+The pmreorder tool is a collection of python scripts designed to parse
+and replay operations logged by pmemcheck - a persistent memory checking tool.
+Pmreorder performs the store reordering between persistent memory barriers -
+a sequence of flush-fence operations. It uses a consistency checking routine
+provided in the command line options to check whether files are in a consistent state.
+
+%files -n pmreorder
+%{_bindir}/pmreorder
+%{_datadir}/pmreorder/*.py
+%{_mandir}/man1/pmreorder.1.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+
+%if %{with ndctl}
+
+%package -n daxio
+Summary: Perform I/O on Device DAX devices or zero a Device DAX device
+Group: __GROUP_SYS_BASE__
+Requires: libpmem__PKG_NAME_SUFFIX__ >= %{version}-%{release}
+%description -n daxio
+The daxio utility performs I/O on Device DAX devices or zero
+a Device DAX device. Since the standard I/O APIs (read/write) cannot be used
+with Device DAX, data transfer is performed on a memory-mapped device.
+The daxio may be used to dump Device DAX data to a file, restore data from
+a backup copy, move/copy data to another device or to erase data from
+a device.
+
+%files -n daxio
+%{_bindir}/daxio
+%{_mandir}/man1/daxio.1.gz
+%license LICENSE
+%doc ChangeLog CONTRIBUTING.md README.md
+
+# end of "if _with_ndctl"
+%endif
+
+%prep
+%setup -q -n %{name}-%{version}
+
+
+%build
+# For debug build default flags may be overridden to disable compiler
+# optimizations.
+CFLAGS="%{optflags}" \
+LDFLAGS="%{?__global_ldflags}" \
+make %{?_smp_mflags} \
+%if %{without ndctl}
+ NDCTL_ENABLE=n \
+%endif
+ __MAKE_FLAGS__
+
+
+# Override LIB_AR with empty string to skip installation of static libraries
+%install
+make install DESTDIR=%{buildroot} \
+%if %{without ndctl}
+ NDCTL_ENABLE=n \
+%endif
+ LIB_AR= \
+ prefix=%{_prefix} \
+ libdir=%{_libdir} \
+ includedir=%{_includedir} \
+ mandir=%{_mandir} \
+ bindir=%{_bindir} \
+ sysconfdir=%{_sysconfdir} \
+ docdir=%{_docdir}
+mkdir -p %{buildroot}%{_datadir}/pmdk
+cp utils/pmdk.magic %{buildroot}%{_datadir}/pmdk/
+__MAKE_INSTALL_FDUPES__
+
+
+%check
+%if 0%{?_skip_check} == 1
+ echo "Check skipped"
+%else
+ %if %{defined _testconfig}
+ cp %{_testconfig} src/test/testconfig.sh
+ %else
+ echo "PMEM_FS_DIR=/tmp" > src/test/testconfig.sh
+ echo "PMEM_FS_DIR_FORCE_PMEM=1" >> src/test/testconfig.sh
+ echo 'TEST_BUILD="debug nondebug"' >> src/test/testconfig.sh
+ echo 'TEST_FS="pmem any none"' >> src/test/testconfig.sh
+ %endif
+ make \
+%if %{without ndctl}
+ NDCTL_ENABLE=n \
+%endif
+ check
+%endif
+
+%post -n libpmem__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n libpmem__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%post -n libpmemblk__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n libpmemblk__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%post -n libpmemlog__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n libpmemlog__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%post -n libpmemobj__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n libpmemobj__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%post -n libpmempool__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n libpmempool__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+
+%if %{with fabric}
+%post -n librpmem__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%postun -n librpmem__PKG_NAME_SUFFIX__ -p /sbin/ldconfig
+%endif
+
+%if 0%{?__debug_package} == 0
+%debug_package
+%endif
+
+
+%changelog
diff --git a/src/pmdk/utils/ps_analyze.ps1 b/src/pmdk/utils/ps_analyze.ps1
new file mode 100644
index 000000000..b0e6bfe9e
--- /dev/null
+++ b/src/pmdk/utils/ps_analyze.ps1
@@ -0,0 +1,31 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017, Intel Corporation
+#
+# ps_analyze -- script to analyze ps1 files
+#
+
+Write-Output "Starting PSScript analyzing ..."
+
+$scriptdir = Split-Path -Parent $PSCommandPath
+$rootdir = $scriptdir + "\.."
+$detected = 0
+
+$include = @("*.ps1" )
+Get-ChildItem -Path $rootdir -Recurse -Include $include | `
+ Where-Object { $_.FullName -notlike "*test*" } | `
+ ForEach-Object {
+ $analyze_result = Invoke-ScriptAnalyzer -Path $_.FullName
+ if ($analyze_result) {
+ $detected = $detected + $analyze_result.Count
+ Write-Output $_.FullName
+ Write-Output $analyze_result
+ }
+ }
+
+if ($detected) {
+ Write-Output "PSScriptAnalyzer FAILED. Issues detected: $detected"
+ Exit 1
+} else {
+ Write-Output "PSScriptAnalyzer PASSED. No issue detected."
+ Exit 0
+}
diff --git a/src/pmdk/utils/sort_solution b/src/pmdk/utils/sort_solution
new file mode 100755
index 000000000..c14f57ece
--- /dev/null
+++ b/src/pmdk/utils/sort_solution
@@ -0,0 +1,128 @@
+#!/usr/bin/perl
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016, Intel Corporation
+
+#
+# sort_solution -- sort visual studio solution projects lists
+#
+
+use strict;
+use warnings;
+# install libtext-diff-perl or perl-Text-Diff
+use Text::Diff;
+
+use Cwd 'abs_path';
+use File::Basename;
+use File::Compare;
+
+
+sub help {
+ print "Usage: sort_solution [check|sort]\n";
+ exit;
+}
+
+sub sort_global_section {
+ my ($solution_fh, $temp_fh, $section_name) = @_;
+ my $line = "";
+ my @array;
+
+ while (defined($line = <$solution_fh>) && ($line !~ $section_name)) {
+ print $temp_fh $line;
+ }
+ print $temp_fh $line;
+
+ while (defined($line = <$solution_fh>) && ($line !~ "EndGlobalSection")) {
+ push @array, $line;
+ }
+
+ @array = sort @array;
+
+ foreach (@array) {
+ print $temp_fh $_;
+ }
+
+ print $temp_fh $line; # print EndGlobalSection line
+}
+
+my $num_args = $#ARGV + 1;
+if ($num_args != 1) {
+ help;
+}
+my $arg = $ARGV[0];
+
+if($arg ne "check" && $arg ne "sort") {
+ help;
+}
+my $filename = dirname(abs_path($0)).'/../src/PMDK.sln';
+my $tempfile = dirname(abs_path($0)).'/../src/temp.sln';
+
+open(my $temp_fh, '>', $tempfile)
+ or die "Could not open file '$tempfile' $!";
+open(my $solution_fh, '<:crlf', $filename)
+ or die "Could not open file '$filename' $!";
+
+my $line;
+
+# Read a header of file
+while (defined($line = <$solution_fh>) && ($line !~ "^Project")) {
+ print $temp_fh $line;
+}
+
+my @part1;
+my $buff;
+my $guid;
+
+# Read the projects list with project dependencies
+do {
+ if($line =~ "^Project") {
+ $buff = $line;
+ $guid = (split(/\,/, $line))[2];
+ } elsif($line =~ "^EndProject") {
+ $buff .= $line;
+ my %table = (
+ guid => $guid,
+ buff => $buff,
+ );
+ push @part1, \%table;
+ } else {
+ $buff .= $line;
+ }
+
+} while (defined($line = <$solution_fh>) && $line ne "Global\n");
+
+# sort the project list by a project GIUD and write to the tempfile
+@part1 = sort { $a->{guid} cmp $b->{guid} } @part1;
+
+foreach (@part1) {
+ my %hash = %$_;
+ print $temp_fh $hash{"buff"};
+}
+print $temp_fh $line; # EndProject line
+
+sort_global_section $solution_fh, $temp_fh, "ProjectConfigurationPlatforms";
+
+sort_global_section $solution_fh, $temp_fh, "NestedProjects";
+
+# read solution file to the end and copy it to the temp file
+while (defined($line = <$solution_fh>)){
+ print $temp_fh $line;
+}
+
+close($temp_fh);
+close($solution_fh);
+
+if($arg eq "check") {
+ my $diff = diff $filename => $tempfile;
+ if ($diff eq "") {
+ unlink $tempfile;
+ exit;
+ }
+
+ print "PMDK solution file is not sorted, " .
+ "please use sort_solution script before pushing your changes\n";
+ unlink $tempfile;
+ exit 1;
+} else {
+ unlink $filename or die "Cannot replace solution file $!";
+ rename $tempfile, $filename;
+}
diff --git a/src/pmdk/utils/style_check.sh b/src/pmdk/utils/style_check.sh
new file mode 100755
index 000000000..c9d44e2a7
--- /dev/null
+++ b/src/pmdk/utils/style_check.sh
@@ -0,0 +1,137 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2016-2020, Intel Corporation
+#
+# utils/style_check.sh -- common style checking script
+#
+set -e
+
+ARGS=("$@")
+CSTYLE_ARGS=()
+CLANG_ARGS=()
+FLAKE8_ARGS=()
+CHECK_TYPE=$1
+
+[ -z "$clang_format_bin" ] && which clang-format-9 >/dev/null &&
+ clang_format_bin=clang-format-9
+[ -z "$clang_format_bin" ] && which clang-format >/dev/null &&
+ clang_format_bin=clang-format
+[ -z "$clang_format_bin" ] && clang_format_bin=clang-format
+
+#
+# print script usage
+#
+function usage() {
+ echo "$0 <check|format> [C/C++ files]"
+}
+
+#
+# require clang-format version 9.0
+#
+function check_clang_version() {
+ set +e
+ which ${clang_format_bin} &> /dev/null && ${clang_format_bin} --version |\
+ grep "version 9\.0"\
+ &> /dev/null
+ if [ $? -ne 0 ]; then
+ echo "SKIP: requires clang-format version 9.0"
+ exit 0
+ fi
+ set -e
+}
+
+#
+# run old cstyle check
+#
+function run_cstyle() {
+ if [ $# -eq 0 ]; then
+ return
+ fi
+
+ ${cstyle_bin} -pP $@
+}
+
+#
+# generate diff with clang-format rules
+#
+function run_clang_check() {
+ if [ $# -eq 0 ]; then
+ return
+ fi
+ check_clang_version
+
+ for file in $@
+ do
+ LINES=$(${clang_format_bin} -style=file $file |\
+ git diff --no-index $file - | wc -l)
+ if [ $LINES -ne 0 ]; then
+ ${clang_format_bin} -style=file $file | git diff --no-index $file -
+ fi
+ done
+}
+
+#
+# in-place format according to clang-format rules
+#
+function run_clang_format() {
+ if [ $# -eq 0 ]; then
+ return
+ fi
+ check_clang_version
+
+ ${clang_format_bin} -style=file -i $@
+}
+
+function run_flake8() {
+ if [ $# -eq 0 ]; then
+ return
+ fi
+ ${flake8_bin} --exclude=testconfig.py,envconfig.py $@
+}
+
+for ((i=1; i<$#; i++)) {
+
+ IGNORE="$(dirname ${ARGS[$i]})/.cstyleignore"
+ if [ -e $IGNORE ]; then
+ if grep -q ${ARGS[$i]} $IGNORE ; then
+ echo "SKIP ${ARGS[$i]}"
+ continue
+ fi
+ fi
+ case ${ARGS[$i]} in
+ *.[ch]pp)
+ CLANG_ARGS+="${ARGS[$i]} "
+ ;;
+
+ *.[ch])
+ CSTYLE_ARGS+="${ARGS[$i]} "
+ ;;
+
+ *.py)
+ FLAKE8_ARGS+="${ARGS[$i]} "
+ ;;
+
+ *)
+ echo "Unknown argument"
+ exit 1
+ ;;
+ esac
+}
+
+case $CHECK_TYPE in
+ check)
+ run_cstyle ${CSTYLE_ARGS}
+ run_clang_check ${CLANG_ARGS}
+ run_flake8 ${FLAKE8_ARGS}
+ ;;
+
+ format)
+ run_clang_format ${CLANG_ARGS}
+ ;;
+
+ *)
+ echo "Invalid parameters"
+ usage
+ exit 1
+ ;;
+esac
diff --git a/src/pmdk/utils/version.sh b/src/pmdk/utils/version.sh
new file mode 100755
index 000000000..fd751c9d9
--- /dev/null
+++ b/src/pmdk/utils/version.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright 2017-2020, Intel Corporation
+#
+# utils/version.sh -- determine project's version
+#
+set -e
+
+if [ -f "$1/VERSION" ]; then
+ cat "$1/VERSION"
+ exit 0
+fi
+
+if [ -f $1/GIT_VERSION ]; then
+ echo -n "\$Format:%h\$" | cmp -s $1/GIT_VERSION - && true
+ if [ $? -eq 0 ]; then
+ PARSE_GIT_VERSION=0
+ else
+ PARSE_GIT_VERSION=1
+ fi
+else
+ PARSE_GIT_VERSION=0
+fi
+
+LATEST_RELEASE=$(cat $1/ChangeLog | grep "* Version" | cut -d " " -f 3 | sort -rd | head -n1)
+
+if [ $PARSE_GIT_VERSION -eq 1 ]; then
+ GIT_VERSION_HASH=$(cat $1/GIT_VERSION)
+
+ if [ -n "$GIT_VERSION_HASH" ]; then
+ echo "$LATEST_RELEASE+git.$GIT_VERSION_HASH"
+ exit 0
+ fi
+fi
+
+cd "$1"
+
+GIT_DESCRIBE=$(git describe 2>/dev/null) && true
+if [ -n "$GIT_DESCRIBE" ]; then
+ # 1.5-19-gb8f78a329 -> 1.5+git19.gb8f78a329
+ # 1.5-rc1-19-gb8f78a329 -> 1.5-rc1+git19.gb8f78a329
+ echo "$GIT_DESCRIBE" | sed "s/\([0-9.]*\)-rc\([0-9]*\)-\([0-9]*\)-\([0-9a-g]*\)/\1-rc\2+git\3.\4/" | sed "s/\([0-9.]*\)-\([0-9]*\)-\([0-9a-g]*\)/\1+git\2.\3/"
+ exit 0
+fi
+
+# try commit it, git describe can fail when there are no tags (e.g. with shallow clone, like on Travis)
+GIT_COMMIT=$(git log -1 --format=%h) && true
+if [ -n "$GIT_COMMIT" ]; then
+ echo "$LATEST_RELEASE+git.$GIT_COMMIT"
+ exit 0
+fi
+
+cd - >/dev/null
+
+# If nothing works, try to get version from directory name
+VER=$(basename `realpath "$1"` | sed 's/pmdk[-]*\([0-9a-z.+-]*\).*/\1/')
+if [ -n "$VER" ]; then
+ echo "$VER"
+ exit 0
+fi
+
+exit 1