diff --git a/Makefile b/Makefile index 144544e..02e76cb 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: scripts/shcompile src/main.sh > zpkg && chmod +x zpkg # minimized build with lxsh -var_exclude = TMPDIR ZPKG_.* _ZPKG_.* SSH_ADDRESS HTTP_ADDRESS PKG_PATH COMPRESSION ALLOW_ROOT UPDATE_REMOVE NOSUDO +var_exclude = TMPDIR ZPKG_.* _ZPKG_.* SSH_ADDRESS HTTP_ADDRESS PKG_PATH COMPRESSION ALLOW_ROOT UPDATE_REMOVE NOSUDO ROOT_PATH DEBUG minimal: minimal-deploy minimal-deploy: minimal-build diff --git a/src/config.sh b/src/config.sh index bbf442e..43bbb23 100644 --- a/src/config.sh +++ b/src/config.sh @@ -10,6 +10,14 @@ virtual_config_path() ln -sf "$old_pkg_path/installed" "$PKG_PATH/installed" } +# defaults +config_path=${ZPKG_ROOT_PATH-$ROOT_PATH}/etc/zpkg +fname="$(basename "$0")" +ALLOW_ROOT=false +UPDATE_REMOVE=true +TMPDIR=${TMPDIR-/tmp} + + # resolve relative config_path config_path="$(resolve_path "$config_path" "$(pwd)")" config_file="$config_path/zpkg.conf" diff --git a/src/deploy.sh b/src/deploy.sh index 79aa0e1..914e39a 100644 --- a/src/deploy.sh +++ b/src/deploy.sh @@ -1,6 +1,5 @@ #!/bin/sh - # $1 = source , $2 = package , $3 = name package() { diff --git a/src/env.sh b/src/env.sh deleted file mode 100644 index 4086aff..0000000 --- a/src/env.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -_OUTPUT=/dev/stdin -[ "$_ZPKG_SELF_UPGRADE" = "y" ] && _OUTPUT=/dev/null - -config_path=$ZPKG_ROOT_PATH/etc/zpkg -fname="$(basename "$0")" -ALLOW_ROOT=false -UPDATE_REMOVE=true - -[ -z "$TMPDIR" ] && TMPDIR=/tmp diff --git a/src/files.sh b/src/files.sh new file mode 100644 index 0000000..46213b6 --- /dev/null +++ b/src/files.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# $1 = file , $2 = prefix , $3 = target to extract +unpack() +{ + echo "Unpacking $1" + $pcompress -dc < "$1" 2>/dev/null | tar -xf - $3 +} + +# $1 = source_dir , $2 = dest_dir , $3 = prefix +copy_files() { + $3 cp -r "$1/." "$2" +} + + +install_files() { + ( + umask a+rx + set -e + if [ -d "ROOT" ] ; then + copy_files ROOT "$ROOT_PATH/" $2 2>/dev/null + fi + if [ -d "HOME" ] ; then + copy_files HOME "$HOME" 2>/dev/null + fi + add_package_entry "$1" $2 + ) +} + +# files from stdin +# $1 = from where , $2 = prefix +delete_files() +{ + cd "$1" || return $? + list=$(cat) + printf "%s\n" "$list" | tr '\n' '\0' | $2 xargs -0 rm -d 2>/dev/null + printf "%s\n" "$list" | tr '\n' '\0' | xargs -0 -n1 dirname | uniq | + tr '\n' '\0' | $2 xargs -0 rmdir -p 2>/dev/null +} + +# stdin: old list +# $1 = old list , $2 = new path +to_delete() +{ + find "$2" -type d 2>/dev/null | sed 's|$|/|g' > tmplist + find "$2" -type f 2>/dev/null >> tmplist + sort tmplist > list + diff --new-line-format="" --unchanged-line-format="" "$1" list + rm tmplist list +} + +# $1 = package , $2 = sudo +remove_files() { + filetree=$(metadata_get tree < "$PKG_PATH/$1.dat" | base64 -d) + printf "%s\n" "$filetree" | grep "^ROOT/" | to_delete - ROOT | sed 's|^ROOT/||g' | tac | delete_files "$ROOT_PATH/" $2 + printf "%s\n" "$filetree" | grep "^HOME/" | to_delete - HOME | sed 's|^HOME/||g' | tac | delete_files "$HOME" +} diff --git a/src/install.sh b/src/install.sh deleted file mode 100644 index 3abe1ce..0000000 --- a/src/install.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh - -# $1 = file , $2 = prefix , $3 = target to extract -unpack() -{ - echo "Unpacking $1" - $pcompress -dc < "$1" 2>/dev/null | tar -xf - $3 -} - -# $1 = package , $2 = prefix -add_package_entry() -{ - ( - set -e - cd "$PKG_PATH" - if grep -q "^$1 " installed 2>/dev/null - then - $2 sed "s|$1 .*\$|$1 $(date +%s)|g" -i installed - else - $2 sh -c "echo '$1 $(date +%s)' >> installed" - $2 chmod a+r installed - fi - ) -} - -# $1 = source_dir , $2 = dest_dir , $3 = prefix -copy_files() { - $3 cp -r "$1/." "$2" -} - -# $1 = package , $2 = prefix -install_package() -{ - [ "$1" = "$fname" ] && [ -z "$opt_R" ] && _self_update=y && return 0 - echo "Installing $1" - tmpdir="$TMPDIR/zpkg_$(random_string 5)" - mkdir -p "$tmpdir" - ( - cd "$tmpdir" || exit $? - fetch_package "$1" || { echo "Package '$1' not found" >&2 && return 1; } - unpack "$1.tar.$extension" $2 || exit $? - gen_metadata "$1.tar.$extension" | $2 tee "$PKG_PATH/$1.dat" >/dev/null - hook install pre "$1" $2 - install_files "$1" $2 - hook install post "$1" $2 - add_package_entry "$1" $2 - ) - ret=$? - rm -rf "$tmpdir" 2>/dev/null - return $ret -} diff --git a/src/view.sh b/src/list.sh similarity index 84% rename from src/view.sh rename to src/list.sh index c895d2a..75115b9 100644 --- a/src/view.sh +++ b/src/list.sh @@ -1,19 +1,5 @@ #!/bin/sh -deps() -{ - ( - cd "$PKG_PATH" - l=$(grep "^$1 " pkglist) || return $? - echo "$l" | cut -d' ' -f3- - ) -} - -# $1 = pkg file -desc() { - cat "$1" | $pcompress -dc 2>/dev/null | tar -xOf - DESC -} - resolve_packages() { RET=0 @@ -47,14 +33,6 @@ resolve_deps() return $RET } -is_installed() -{ - ( - cd "$PKG_PATH" - grep -q "^$1 " installed 2>/dev/null - ) -} - # $1 = file view_package_file() { tree=$(cat "$1" | $pcompress -dc 2>/dev/null | tar -tf - 2>/dev/null) || exit $? diff --git a/src/main.sh b/src/main.sh index 7f3d009..674459c 100644 --- a/src/main.sh +++ b/src/main.sh @@ -3,9 +3,7 @@ [ "$DEBUG" = true ] && set -x # ordered requirements -%include util.sh env.sh print.sh -%include options.sh -%include config.sh +%include util.sh options.sh config.sh # everything else %include *.sh diff --git a/src/metadata.sh b/src/metadata.sh index 50a22ec..4751b3a 100644 --- a/src/metadata.sh +++ b/src/metadata.sh @@ -1,3 +1,38 @@ +#!/bin/sh + +# $1 = package , $2 = prefix +add_package_entry() +{ + ( + set -e + cd "$PKG_PATH" + if grep -q "^$1 " installed 2>/dev/null ; then + $2 sed "s|$1 .*\$|$1 $(date +%s)|g" -i installed + else + $2 sh -c "echo '$1 $(date +%s)' >> installed" + $2 chmod a+r installed + fi + ) +} + +deps() +{ + ( + cd "$PKG_PATH" + l=$(grep "^$1 " pkglist) || return $? + echo "$l" | cut -d' ' -f3- + ) +} + +# $1 = package +is_installed() +{ + ( + cd "$PKG_PATH" + grep -q "^$1 " installed 2>/dev/null + ) +} + # stdin = metadata # $1 = value metadata_get() { @@ -29,12 +64,12 @@ gen_metadata() { printf "installsize=%s\n" "$isize" gen_hook_metadata printf "tree=%s\n" "$(find ROOT HOME ! -type d 2>/dev/null | base64 -w0)" - printf "dirtree=%s\n" "$(find ROOT HOME -type d -mindepth 1 2>/dev/null | base64 -w0)" + printf "dirtree=%s\n" "$(find ROOT HOME -mindepth 1 -type d 2>/dev/null | base64 -w0)" } # $1 = sudo convert_to_metadata() { - find "$PKG_PATH" -type f -maxdepth 1 -name "*.tar.$extension" | + find "$PKG_PATH" -maxdepth 1 -type f -name "*.tar.$extension" | while read -r I ; do pkgname=$(basename "${I%.tar.$extension}") echo "Migrate $pkgname" diff --git a/src/operation.sh b/src/operation.sh new file mode 100644 index 0000000..6d52ff4 --- /dev/null +++ b/src/operation.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +# $1 = package , $2 = prefix +install_package() +{ + [ "$1" = "$fname" ] && [ -z "$opt_R" ] && _self_update=y && return 0 + echo "Installing $1" + tmpdir="$TMPDIR/zpkg_$(random_string 5)" + mkdir -p "$tmpdir" + ( + cd "$tmpdir" || exit $? + fetch_package "$1" || { echo "Package '$1' not found" >&2 && return 1; } + unpack "$1.tar.$extension" $2 || exit $? + gen_metadata "$1.tar.$extension" | $2 tee "$PKG_PATH/$1.dat" >/dev/null + hook install pre "$1" $2 + install_files "$1" $2 + hook install post "$1" $2 + add_package_entry "$1" $2 + ) + ret=$? + rm -rf "$tmpdir" 2>/dev/null + return $ret +} + +# $1 = package , $2 = prefix +remove_package() +{ + if [ ! -f "$PKG_PATH/$1.dat" ] || ! grep -q "^$1 " "$PKG_PATH/installed" + then + echo "Package '$1' not installed" >&2 + return 1 + fi + + echo "Removing $1" + + hook remove pre "$1" $2 + remove_files "$1" $2 + hook remove post "$1" $2 + $2 rm -f "$PKG_PATH/$1.dat" 2>/dev/null + $2 sed -i "/^$1 /d" "$PKG_PATH/installed" + +} + +# $1 = package , $2 = prefix +upgrade_package() +{ + [ "$1" = "$fname" ] && [ -z "$opt_R" ] && _self_update=y && return 0 + echo "Updating $1" + tmpdir="$TMPDIR/zpkg_$(random_string 5)" + mkdir -p "$tmpdir" + ( + # fetch package + cd "$tmpdir" + fetch_package "$1" || { echo "Package '$1' not found" >&2 && return 1; } + unpack "$1.tar.$extension" || return $? + + hook upgrade pre "$1" $2 + remove_files "$1" $2 + gen_metadata . | $2 tee "$PKG_PATH/$1.dat" >/dev/null + install_files "$1" $2 + hook upgrade post "$1" $2 + ) + ret=$? + rm -rf "$tmpdir" 2>/dev/null + return $ret +} + +## self upgrading mitigation + +_OUTPUT=/dev/stdin +[ "$_ZPKG_SELF_UPGRADE" = "y" ] && _OUTPUT=/dev/null + +unset _self_update +do_self_update() +{ + _tmpzpkg="$TMPDIR/zpkg_bin_$(random_string 5)" + # copy current file + cp "$0" "$_tmpzpkg" || return $? + exec sh -c '_ZPKG_SELF_UPGRADE=y "$1" -c "$2" -R install zpkg ; rm -f "$1"' sh "$_tmpzpkg" "$config_path" +} diff --git a/src/process.sh b/src/process.sh deleted file mode 100644 index 4e4f791..0000000 --- a/src/process.sh +++ /dev/null @@ -1,20 +0,0 @@ -install_files() { - ( - umask a+rx - set -e - if [ -d "ROOT" ] ; then - copy_files ROOT "$ROOT_PATH/" $2 2>/dev/null - fi - if [ -d "HOME" ] ; then - copy_files HOME "$HOME" 2>/dev/null - fi - add_package_entry "$1" $2 - ) -} - -# $1 = package , $2 = sudo -remove_files() { - filetree=$(metadata_get tree < "$PKG_PATH/$1.dat" | base64 -d) - printf "%s\n" "$filetree" | grep "^ROOT/" | to_delete - ROOT | sed 's|^ROOT/||g' | tac | delete_files "$ROOT_PATH/" $2 - printf "%s\n" "$filetree" | grep "^HOME/" | to_delete - HOME | sed 's|^HOME/||g' | tac | delete_files "$HOME" -} diff --git a/src/remove.sh b/src/remove.sh deleted file mode 100644 index 9935c2d..0000000 --- a/src/remove.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/sh - -# files from stdin -# $1 = from where , $2 = prefix -delete_files() -{ - cd "$1" || return $? - list=$(cat) - printf "%s\n" "$list" | tr '\n' '\0' | $2 xargs -0 rm -d 2>/dev/null - printf "%s\n" "$list" | tr '\n' '\0' | xargs -0 -n1 dirname | uniq | - tr '\n' '\0' | $2 xargs -0 rmdir -p 2>/dev/null -} - -# stdin: old list -# $1 = old list , $2 = new path -to_delete() -{ - find "$2" -type d 2>/dev/null | sed 's|$|/|g' > tmplist - find "$2" -type f 2>/dev/null >> tmplist - sort tmplist > list - diff --new-line-format="" --unchanged-line-format="" "$1" list - rm tmplist list -} - -# $1 = package , $2 = prefix -remove_package() -{ - if [ ! -f "$PKG_PATH/$1.dat" ] || ! grep -q "^$1 " "$PKG_PATH/installed" - then - echo "Package '$1' not installed" >&2 - return 1 - fi - - echo "Removing $1" - - hook remove pre "$1" $2 - remove_files "$1" $2 - hook remove post "$1" $2 - $2 rm -f "$PKG_PATH/$1.dat" 2>/dev/null - $2 sed -i "/^$1 /d" "$PKG_PATH/installed" - -} diff --git a/src/upgrade.sh b/src/upgrade.sh deleted file mode 100644 index 315b21c..0000000 --- a/src/upgrade.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# $1 = package , $2 = prefix -upgrade_package() -{ - [ "$1" = "$fname" ] && [ -z "$opt_R" ] && _self_update=y && return 0 - echo "Updating $1" - tmpdir="$TMPDIR/zpkg_$(random_string 5)" - mkdir -p "$tmpdir" - ( - # fetch package - cd "$tmpdir" - fetch_package "$1" || { echo "Package '$1' not found" >&2 && return 1; } - unpack "$1.tar.$extension" || return $? - - hook upgrade pre "$1" $2 - remove_files "$1" $2 - gen_metadata . | $2 tee "$PKG_PATH/$1.dat" >/dev/null - install_files "$1" $2 - hook upgrade post "$1" $2 - ) - ret=$? - rm -rf "$tmpdir" 2>/dev/null - return $ret -} - -## self upgrading mitigation - -unset _self_update -do_self_update() -{ - _tmpzpkg="$TMPDIR/zpkg_bin_$(random_string 5)" - # copy current file - cp "$0" "$_tmpzpkg" || return $? - exec sh -c '_ZPKG_SELF_UPGRADE=y "$1" -c "$2" -R install zpkg ; rm -f "$1"' sh "$_tmpzpkg" "$config_path" -}