First commit

A modified copy of portzap repurposed for management of the
hardenedbsd source tree.
This commit is contained in:
0x1eef 2024-05-11 16:03:00 -03:00
commit ea06f0dfbc
17 changed files with 534 additions and 0 deletions

16
.github/workflows/shellcheck.yml vendored Normal file
View file

@ -0,0 +1,16 @@
name: srczap
permissions: {}
jobs:
shellcheck:
name: shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ludeeus/action-shellcheck@master
- run: make shellcheck
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

1
.projectile Normal file
View file

@ -0,0 +1 @@
-/.git

15
LICENSE Normal file
View file

@ -0,0 +1,15 @@
Copyright (C) 2023 by 0x1eef <0x1eef@protonmail.com>
Permission to use, copy, modify, and/or distribute this
software for any purpose with or without fee is hereby
granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.

24
Makefile Normal file
View file

@ -0,0 +1,24 @@
PREFIX = /usr/local
BINDIR = $(PREFIX)/bin
MANDIR = $(PREFIX)/man/man8
LIBEXECDIR = $(PREFIX)/libexec/srczap
SHAREDIR = $(PREFIX)/share/srczap
install:
install -d $(BINDIR) $(LIBEXECDIR) $(SHAREDIR) $(MANDIR)
install -m 0755 bin/srczap $(BINDIR)
install -m 0755 bin/setup-srczap $(BINDIR)
install -m 0755 libexec/srczap/* $(LIBEXECDIR)
install -m 0644 share/srczap/* $(SHAREDIR)
install -m 0644 man/man8/srczap.8 $(MANDIR)
deinstall:
rm $(BINDIR)/srczap
rm $(BINDIR)/setup-srczap
rm $(MANDIR)/srczap.8
rm -rf $(LIBEXECDIR)
rm -rf $(SHAREDIR)
shellcheck:
shellcheck bin/srczap
shellcheck libexec/srczap/*

36
bin/setup-srczap Executable file
View file

@ -0,0 +1,36 @@
#!/bin/sh -e
##
# variables
localbase="${LOCALBASE:-/usr/local}"
conf=$(cat "${localbase}"/share/srczap/doas.conf)
doas="${localbase}"/etc/doas.conf
##
# main
if [ "$(id -u)" != "0" ]; then
echo "[-] This command must be run by root"
exit 1
fi
if id -u _srczap > /dev/null 2>&1; then
echo "[-] The _srczap user exists"
echo "[-] Add user(s) to the _srczap group:"
echo "root# pw groupmod -n _srczap -m user1,user2"
else
pw useradd -n _srczap \
-c "srczap user" \
-m \
-s /sbin/nologin
chmod u=rwX,g=rX,o= /home/_srczap/
echo "[-] The _srczap user, group and home directory have been created."
echo "[-] Add user(s) to the _srczap group:"
echo "root# pw groupmod -n _srczap -m user1,user2"
fi
if grep -F "^${conf}$" "${doas}" > /dev/null 2>&1; then
echo "[-] No changes made to ${doas}"
else
echo "$conf" >> "$doas"
echo "[-] ${doas} has been changed. Please review the changes"
fi

64
bin/srczap Executable file
View file

@ -0,0 +1,64 @@
#!/bin/sh -e
##
# variables
localbase="${LOCALBASE:-/usr/local}"
gitdir="/home/_srczap/src"
giturl="${SRCZAP_GITURL:-https://git.hardenedbsd.org/hardenedbsd/HardenedBSD/}"
branch="${SRCZAP_BRANCH:-hardened/14-stable/master}"
installdir="${SRCZAP_INSTALLDIR:-/usr/src}"
revision="${installdir}"/.srczap
libexec="${localbase}"/libexec/srczap
##
# functions
require_dependency() {
deps=$1
for dep in $deps; do
if ! which -s "$dep"; then
echo "[-] This command requires ${dep}, but ${dep} wasn't found"
exit 1
fi
done
}
##
# main
i=1
while [ "${i}" -le "$#" ]; do
eval "_srczap_option=\$${i}"
# shellcheck disable=SC2154
if [ "${_srczap_option}" = "-v" ]; then
cat "${localbase}"/share/srczap/VERSION
exit 0
fi
# shellcheck disable=SC2003
i=$(expr "${i}" + 1);
done
case $1 in
"clone")
require_dependency "git doas"
"${libexec}"/srczap-clone "${giturl}" "${gitdir}" "${branch}"
;;
"pull")
require_dependency "git doas"
"${libexec}"/srczap-pull "${gitdir}" "${branch}"
;;
"erase")
"${libexec}"/srczap-erase "${gitdir}" "${installdir}"
;;
"install")
require_dependency "git doas"
"${libexec}"/srczap-install "${gitdir}" "${installdir}" "${revision}"
;;
*)
printf "Usage: srczap COMMAND [OPTIONS]\n"
printf "\n"
printf "Commands:\n"
printf " clone Clone the HardenedBSD source code\n"
printf " pull Pull source code updates\n"
printf " erase Erase /usr/src/ and /home/_srczap/src/\n"
printf " install Install the source tree into /usr/src/\n"
;;
esac

View file

@ -0,0 +1,25 @@
#!/bin/sh -e
##
# variables
localbase=${LOCALBASE:-/usr/local}
git="${localbase}"/bin/git
gitdir=$1
commit=$2
mode=u=rwX,g=rX,o=
##
# functions
gitexec()
{
doas -n -u _srczap \
/bin/sh -c "umask ${mode}; ${git} ${1}"
}
##
# main
cd "${gitdir}"
add=$(gitexec "diff --name-only --diff-filter=A ${commit} HEAD")
mod=$(gitexec "diff --name-only --diff-filter=M ${commit} HEAD")
echo "${add}"
echo "${mod}"

View file

@ -0,0 +1,22 @@
#!/bin/sh -e
##
# variables
localbase=${LOCALBASE:-/usr/local}
git="${localbase}"/bin/git
gitdir=$1
commit=$2
mode=u=rwX,g=rX,o=
##
# functions
gitexec()
{
doas -n -u _srczap \
/bin/sh -c "umask ${mode}; ${git} ${1}"
}
##
# main
cd "${gitdir}"
gitexec "diff --name-only --diff-filter=D ${commit} HEAD"

20
libexec/srczap/git-rev Normal file
View file

@ -0,0 +1,20 @@
#!/bin/sh -e
##
# variables
git=/usr/local/bin/git
gitdir=$1
mode=u=rwX,g=rX,o=
##
# functions
gitexec()
{
doas -n -u _srczap \
/bin/sh -c "umask ${mode}; ${git} ${1}"
}
##
# main
cd "${gitdir}"
gitexec "rev-parse HEAD"

View file

@ -0,0 +1,11 @@
#!/bin/sh -e
group="_srczap"
if id -Gn | \
tr ' ' '\n' | \
grep -e "^${group}$" \
> /dev/null 2>&1; then
exit 0
else
exit 1
fi

41
libexec/srczap/srczap-clone Executable file
View file

@ -0,0 +1,41 @@
#!/bin/sh -e
##
# variables
localbase=${LOCALBASE:-/usr/local}
libexec=$(dirname "$0")
git="${localbase}"/bin/git
giturl=$1
gitdir=$2
branch=$3
mode=u=rwX,g=rX,o=
##
# functions
gitexec()
{
doas -n -u _srczap \
/bin/sh -c "umask ${mode}; ${git} ${1}"
}
##
# main
if ! "${libexec}"/issrczap-member; then
echo "[-] This command must be run by a member of the '_srczap' group"
exit 1
fi
if [ -e "${gitdir}/.git" ]; then
echo "[-] ${gitdir} exists."
echo "[-] Try 'srczap pull'"
exit 1
fi
set -x
gitexec "clone ${giturl} ${gitdir}"
cd "${gitdir}"
gitexec "config core.filemode off"
set +x
echo "[-] git checkout ${branch}"
gitexec "checkout -t origin/${branch} > /dev/null 2>&1"
echo "[-] Done"

View file

@ -0,0 +1,43 @@
#!/bin/sh -e
##
# variables
gitdir=$1
installdir=$2
##
# main
if [ "$(id -u)" != "0" ]; then
echo "[-] This command must be run by root"
exit 1
fi
printf "[-] Are you sure ? \n"
printf "[-] These directories will be erased:\n"
printf " [*] %s \n" "${gitdir}"
printf " [*] %s \n" "${installdir}"
printf "[y|n] "
while true; do
read -r r
if [ "${r}" = "y" ]; then
break
elif [ "${r}" = "n" ]; then
printf "[-] Nothing to do\n"
exit
else
printf "[-] '%s' is not a valid option.\n" "${r}"
printf "[y|n] "
fi
done
for dir in "${gitdir}" "${installdir}"; do
printf "%s " "${dir}"
find "${dir}" \
-maxdepth 1 \
\! -name "." \
\! -name ".." \
\! -name "src" \
-exec printf . \; \
-exec rm -rf "{}" \;
echo
done
printf "[-] Done\n"

77
libexec/srczap/srczap-install Executable file
View file

@ -0,0 +1,77 @@
#!/bin/sh -e
##
# variables
gitdir=$1
installdir=$2
revfile=$3
libexec=$(dirname "$0")
mode="u=rwX,g=rX,o="
##
# functions
perform_update()
{
rev=$(cat "${revfile}")
add=$("${libexec}"/git-changed-files "${gitdir}" "${rev}")
del=$("${libexec}"/git-removed-files "${gitdir}" "${rev}")
for file in ${del}; do
target="${installdir}/${file}"
parent=$(dirname "${target}")
echo "rm ${target}"
rm -f "${target}"
find "${parent}" -type d -maxdepth 0 -empty -delete
done
for file in ${add}; do
target="${installdir}/${file}"
parent=$(dirname "${target}")
parents=""
while [ ! -e "${parent}" ]; do
parents="${parent} ${parents}"
parent=$(dirname "${parent}")
done
for dir in ${parents}; do
run_install "-d" "${dir}"
done
run_install "${file}" "${target}"
done
}
perform_install()
{
find -s . \
-maxdepth 1 \
! -name "." \
! -name ".git" \
! -name ".gitignore" \
! -name ".hooks" \
! -name ".arcconfig" \
-exec cp -Rpv {} "${installdir}" \;
set -x
chown -R root "${installdir}"
}
run_install()
{
install -o root -g _srczap -m "${mode}" -v "$@"
}
##
# main
if [ "$(id -u)" != "0" ]; then
echo "[-] This command must be run by root"
exit 1
fi
set -x
umask ${mode}
cd "${gitdir}"
set +x
run_install "-d" "${installdir}"
chmod ${mode} "${installdir}"
if [ -e "${revfile}" ]; then
perform_update
else
perform_install
fi
"${libexec}"/git-rev "${gitdir}" > "${revfile}"

59
libexec/srczap/srczap-pull Executable file
View file

@ -0,0 +1,59 @@
#!/bin/sh -e
##
# variables
libexec=$(dirname "$0")
localbase=${LOCALBASE:-/usr/local}
git="${localbase}"/bin/git
gitdir=$1
branch=$2
mode="u=rwX,g=rX,o="
##
# functions
gitexec()
{
doas -n -u _srczap \
/bin/sh -c "umask ${mode}; ${git} ${1}"
}
change_branch()
{
set +e
remote=$1
branch=$2
echo "[-] Attempt to change branch: ${branch}"
gitexec "fetch ${remote} > /dev/null 2>&1"
if ! gitexec "checkout ${branch} > /dev/null 2>&1" ||
gitexec "checkout -t ${remote}/${branch} > /dev/null 2>&1"; then
r="${?}"
echo "[-] 'git checkout' exited with an error"
exit "${r}"
else
echo "[-] Done"
fi
set -e
}
##
# main
if ! "${libexec}"/issrczap-member; then
echo "[-] This command must be run by a member of the '_srczap' group"
exit 1
fi
if [ ! -e "${gitdir}/.git" ]; then
set +x
echo "[-] ${gitdir} is not a valid git repository."
echo "[-] Try 'srczap clone'"
exit 1
fi
cd "${gitdir}"
remote=$(gitexec "remote" | head -n1)
cbranch=$(gitexec "branch --show-current")
if [ "${cbranch}" != "${branch}" ]; then
change_branch "${remote}" "${branch}"
fi
set -x
gitexec "pull --rebase ${remote} ${branch}"

75
man/man8/srczap.8 Normal file
View file

@ -0,0 +1,75 @@
.Dd May 2023
.Dt SRCZAP 8
.Os
.Sh NAME
.Nm srczap
.Nd manages a copy of the HardenedBSD source code
.Sh SYNOPSIS
.br
srczap clone
.br
srczap pull
.br
srczap install
.br
srczap erase
.Sh DESCRIPTION
.Nm srczap
manages a copy of the HardenedBSD source code.
The copy of the source tree is maintained by members of
the '_srczap' group, and a copy of the source tree
can be installed to /usr/src/ by root.
.Sh EXAMPLES
.sp
.sp
.Nm srczap clone
.br
Clone the hardenedbsd ports tree into /home/_srczap/src/.
.br
This command is delegated to the '_srczap' user.
.Pp
.Nm srczap pull
.br
Pull updates into /home/_srczap/src/.
.br
This command is delegated to the '_srczap' user.
.Pp
.Nm srczap install
.br
Install /home/_srczap/src/ into /usr/src/.
.br
This command requires root privileges.
.Pp
.Nm srczap erase
.br
Start over: erase /usr/src/ and /home/_srczap/src/.
.br
This command requires root privileges.
.br
.Sh ENVIRONMENT
.sp
.sp
.Nm SRCZAP_GITURL
.br
The URL to a git repository.
.br
Default: https://git.hardenedbsd.org/hardenedbsd/HardenedBSD/
.sp
.Nm SRCZAP_BRANCH
.br
The git branch to clone and pull updates from.
.br
Default: hardened/14-stable/master
.br
.sp
.Nm SRCZAP_INSTALLDIR
.br
The directory where the ports collection will be installed.
.br
Default: /usr/src/
.sp
.Sh AUTHORS
The
.Nm srczap
utility and this manual page were written by
0x1eef <0x1eef@protonmail.com>.

1
share/srczap/VERSION Normal file
View file

@ -0,0 +1 @@
v0.1.0-dev

4
share/srczap/doas.conf Normal file
View file

@ -0,0 +1,4 @@
##
# srczap
permit nopass root as _srczap cmd /bin/sh
permit nopass :_srczap as _srczap cmd /bin/sh