Permalink
Browse files

update-packages: several reliability checks

* lock to avoid multiple concurrent runs

* when upgrading, check if the files removed are inside the devPanel install
  (i.e. refuse to remove files outside the devPanel dir)

* more checks for malformed lines on the updates file
  • Loading branch information...
vmmello committed Jun 29, 2016
1 parent 15d2e0f commit 2d0cc79e6bb4024364ea7904894bb31bea477254
Showing with 73 additions and 35 deletions.
  1. +1 −0 .gitignore
  2. +2 −12 lib/functions
  3. +69 −23 libexec/update-packages
  4. +1 −0 var/lock/.keepme
@@ -9,3 +9,4 @@
/compat/w_/public_html/
!/compat/w_/public_html/cgi/cgit.cgi
/config/os
/var/lock/
@@ -899,12 +899,7 @@ lock_path() {

local lock_file=""

if [ ! -L "$path" -a ! -e "$path" ]; then
wedp_warn "path '$path' doesn't exist"
return 1
else
lock_file="`dirname "$path"`/.`basename "$path"`.lock"
fi
lock_file="`dirname "$path"`/.`basename "$path"`.lock"

local -i retries=1
while [ $retries -le $max_retries ]; do
@@ -927,12 +922,7 @@ unlock_path() {

local lock_file=""

if [ ! -L "$path" -a ! -e "$path" ]; then
wedp_warn "path '$path' doesn't exist"
return 1
else
lock_file="`dirname "$path"`/.`basename "$path"`.lock"
fi
lock_file="`dirname "$path"`/.`basename "$path"`.lock"

if [ ! -L "$lock_file" -a ! -e "$lock_file" ]; then
wedp_warn "didn't find lock file '$lock_file'"
@@ -122,33 +122,44 @@ remove_leftover_files() {
if [ -s "$old_others_txt" ]; then
[ -n "$verbose" ] && echo "Removing left over files..."
while read file; do
[ -n "$verbose" ] && echo " $file"
rm -f "$file"
if is_inside_system_dir "$file"; then
[ -n "$verbose" ] && echo " $file"
rm -f "$file"
else
echo " Warning: file $file is outside directory $system_dir, skipping..." 1>&2
sleep 1
fi
done < "$old_others_txt"
fi

# now remove directories of the package
if [ -s "$old_dirs_txt" ]; then
local dir_name
[ -n "$verbose" ] && echo "Removing left over directories..."
while read dir_name; do
n_entries=$(stat -c '%h' "$dir_name")
if [ $? -ne 0 ]; then
echo "Warning: unable to get number of entries in dir $dir_name." 1>&2
continue
fi

if [ $n_entries -eq 2 ]; then
[ -n "$verbose" ] && echo " $dir_name/"
# using rmdir to remove only empty directories (as files have been
# removed in the previous step). Not using rm -rf $dir_name not to
# remove system dirs (e.g. bin/ ) that are common to all packages
#
# By using rmdir it'll remove only non-empty directories.

rmdir "$dir_name" 2>/dev/null
while read dir_name; do
if is_inside_system_dir "$dir_name"; then
n_entries=$(stat -c '%h' "$dir_name")
if [ $? -ne 0 ]; then
echo "Warning: unable to get number of entries in dir $dir_name." 1>&2
continue
fi

if [ $n_entries -eq 2 ]; then
[ -n "$verbose" ] && echo " $dir_name/"
# using rmdir to remove only empty directories (as files have been
# removed in the previous step). Not using rm -rf $dir_name not to
# remove system dirs (e.g. bin/ ) that are common to all packages
#
# By using rmdir it'll remove only non-empty directories.

rmdir "$dir_name" 2>/dev/null
else
[ -n "$verbose" ] && echo " $dir_name (keeping, not empty)"
fi
else
[ -n "$verbose" ] && echo " $dir_name (keeping, not empty)"
echo " Warning: directory $dir_name is outside directory $system_dir, skipping..." 1>&2
sleep 1
fi
done < "$old_dirs_txt"
fi
@@ -391,6 +402,23 @@ usage() {
exit 1
}

cleanup() {
unlock_path "$lock_file"

[ -d "$tmp_dir" ] && rm -rf "$tmp_dir"
}

is_inside_system_dir() {
local path="$1"
local system_dir="${2:-$system_dir}"

if [ "${path#$system_dir/}" == "$path" ]; then
return 1
else
return 0
fi
}

# main

declare -i verbose=0
@@ -419,6 +447,7 @@ self_bin=`readlink -e "$0"`
curr_dir=`dirname "$self_bin"`
system_dir=`readlink -e "$curr_dir/.."`
lib_file="$system_dir/lib/functions"
lock_file="$system_dir/var/lock/${0##*/}"

if ! source "$lib_file"; then
echo "Error: unable to source file '$lib_file'" 1>&2
@@ -430,13 +459,17 @@ if deref_os_prop "$system_dir" no_package_updates &>/dev/null; then
error "this system is configured not to have automated updates."
fi

if ! lock_path "$lock_file" >/dev/null; then
error "unable to lock. There's probably another instance running."
fi

# should not use /tmp here because the need to execute post-install and
# post-update scripts, and it breaks if /tmp is mounted with noexec
if ! tmp_dir=`mktemp -d "$system_dir/var/tmp/tmp.XXXXXX"`; then
error "unable to create temporary directory"
fi
trap 'exit 1' INT HUP TERM QUIT
trap 'rm -rf "$tmp_dir"' EXIT
trap 'cleanup' EXIT

updates_file="$tmp_dir/updates_$base_channel.txt"

@@ -462,7 +495,9 @@ if [ $? -ne 0 -o -z "$linux_arch" ]; then
fi

declare -i n_updated=0 n_failed_update=0 n_installed=0 n_failed_install=0
declare -i line_n=0
while read update_line; do
line_n+=1
# ignore: empty lines, line with only spaces or lines starting with "#"
if [ -z "$update_line" ] || [[ "$update_line" =~ ^\ +$ ]] || \
[[ "$update_line" =~ ^\ *# ]]; then
@@ -471,11 +506,18 @@ while read update_line; do

unset v_installed v_needs_update

IFS=$'\t' read package serial latest_version pkg_distro \
pkg_distro_version arch sha512_str flags <<< "$update_line"
declare -a fields_ar=( package serial latest_version pkg_distro \
pkg_distro_version arch sha512_str flags )

pkg_url=`assemble_pkg_url "$packages_url" "$package" "$latest_version" \
"$pkg_distro" "$pkg_distro_version" "$arch"`
IFS=$'\t' read "${fields_ar[@]}" <<< "$update_line"

for field in "${fields_ar[@]}"; do
if [ -z "${!field}" ]; then
echo "Warning: missing field $field on line $line_n" 1>&2
sleep 1
continue
fi
done

# this avoids a package from being installed or updated more than once
# when there are multiple rules (e.g. a package with specific distro versions and
@@ -521,6 +563,10 @@ while read update_line; do

if [ -z "$v_installed" -o -n "$v_needs_update" ]; then
pkg_file="$tmp_dir/"

pkg_url=`assemble_pkg_url "$packages_url" "$package" "$latest_version" \
"$pkg_distro" "$pkg_distro_version" "$arch"`

pkg_file+=`assemble_pkg_filename "$package" "$latest_version" \
"$pkg_distro" "$pkg_distro_version" "$arch"`

@@ -0,0 +1 @@
Keep this file. For git clones to create the whole structure.

0 comments on commit 2d0cc79

Please sign in to comment.