mirror of
https://codeberg.org/kiss-community/kiss
synced 2024-12-24 08:00:05 -07:00
kiss: unique temporary files
All temporary files now have unique names and reuse of the same file for multiple purposes has been removed. This prevents issues where a failed write to a log file used in multiple places can cause prior data to be read elsewhere in the package manager.
This commit is contained in:
parent
e853e1accc
commit
9895a14e83
105
kiss
105
kiss
@ -44,6 +44,29 @@ contains() {
|
||||
case " $1 " in *" $2 "*) return 0; esac; return 1
|
||||
}
|
||||
|
||||
tmp_file() {
|
||||
# Create a uniquely named temporary file and store its absolute path
|
||||
# in a variable (_tmp_file).
|
||||
#
|
||||
# To prevent subshell usage and to handle cases where multiple files
|
||||
# are needed, this saves the last two temporary files to variables
|
||||
# for access by the caller (allowing 3 files at once).
|
||||
_tmp_file_pre_pre=$_tmp_file_pre
|
||||
_tmp_file_pre=$_tmp_file
|
||||
_tmp_file=$mak_dir/.$pid-$1-$2
|
||||
|
||||
: > "$_tmp_file" ||
|
||||
die "$1" "Failed to create temporary file"
|
||||
}
|
||||
|
||||
tmp_file_copy() {
|
||||
# Create a uniquely named temporary file and make a duplicate of
|
||||
# the file in '$3' if it exists.
|
||||
tmp_file "$1" "$2"
|
||||
|
||||
! [ -f "$3" ] || cp -f "$3" "$_tmp_file"
|
||||
}
|
||||
|
||||
prompt() {
|
||||
[ "$1" ] && log "$1"
|
||||
|
||||
@ -925,8 +948,10 @@ pkg_verify() {
|
||||
set -- "$@" "$chk"
|
||||
done 2>/dev/null < "$repo_dir/checksums"
|
||||
|
||||
tmp_file "$1" verify
|
||||
|
||||
# Generate a new set of checksums to compare against.
|
||||
pkg_checksums "$1" > "$mak_dir/v"
|
||||
pkg_checksums "$1" > "$_tmp_file"
|
||||
|
||||
# Check that the first column (separated by whitespace) match in both
|
||||
# checksum files. If any part of either file differs, mismatch. Abort.
|
||||
@ -938,13 +963,16 @@ pkg_verify() {
|
||||
|
||||
*) die "${repo_dir##*/}" "Checksum mismatch"
|
||||
esac
|
||||
done < "$mak_dir/v"
|
||||
done < "$_tmp_file"
|
||||
}
|
||||
|
||||
pkg_conflicts() {
|
||||
# Check to see if a package conflicts with another.
|
||||
log "$1" "Checking for package conflicts"
|
||||
|
||||
tmp_file "$1" manifest-files
|
||||
tmp_file "$1" found-conflicts
|
||||
|
||||
# Filter the tarball's manifest and select only files. Resolve all
|
||||
# symlinks in file paths as well.
|
||||
while read -r file; do
|
||||
@ -961,7 +989,7 @@ pkg_conflicts() {
|
||||
# Print the file with all symlinks in its path
|
||||
# resolved to their real locations.
|
||||
printf '%s\n' "${PWD#"$KISS_ROOT"}/${file##*/}"
|
||||
done < "$tar_dir/$1/$pkg_db/$1/manifest" > "$mak_dir/cf_m"
|
||||
done < "$tar_dir/$1/$pkg_db/$1/manifest" > "$_tmp_file_pre"
|
||||
|
||||
cd "$tar_dir/$1"
|
||||
|
||||
@ -989,16 +1017,16 @@ pkg_conflicts() {
|
||||
# Store the list of found conflicts in a file as we'll be using the
|
||||
# information multiple times. Storing things in the cache dir allows
|
||||
# us to be lazy as they'll be automatically removed on script end.
|
||||
grep -Fxf "$mak_dir/cf_m" -- "$@" 2>/dev/null > "$mak_dir/cf" || :
|
||||
grep -Fxf "$_tmp_file_pre" -- "$@" 2>/dev/null > "$_tmp_file" || :
|
||||
|
||||
# Enable alternatives automatically if it is safe to do so.
|
||||
# This checks to see that the package that is about to be installed
|
||||
# doesn't overwrite anything it shouldn't in '/var/db/kiss/installed'.
|
||||
grep -q ":/var/db/kiss/installed/" "$mak_dir/cf" || choice_auto=1
|
||||
grep -q ":/var/db/kiss/installed/" "$_tmp_file" || choice_auto=1
|
||||
|
||||
if [ "$KISS_CHOICE" != 0 ] &&
|
||||
[ "$choice_auto" = 1 ] &&
|
||||
[ -s "$mak_dir/cf" ]; then
|
||||
[ -s "$_tmp_file" ]; then
|
||||
# This is a novel way of offering an "alternatives" system.
|
||||
# It is entirely dynamic and all "choices" are created and
|
||||
# destroyed on the fly.
|
||||
@ -1042,7 +1070,7 @@ pkg_conflicts() {
|
||||
log "this must be fixed in $p_name. Contact the maintainer"
|
||||
die "by finding their details via 'kiss-maintainer'" "" "!>"
|
||||
}
|
||||
done < "$mak_dir/cf"
|
||||
done < "$_tmp_file"
|
||||
|
||||
log "$p_name" "Converted all conflicts to choices (kiss a)"
|
||||
|
||||
@ -1050,7 +1078,7 @@ pkg_conflicts() {
|
||||
# to its new spot (and name) in the choices directory.
|
||||
pkg_manifest "$p_name" "$tar_dir" 2>/dev/null
|
||||
|
||||
elif [ -s "$mak_dir/cf" ]; then
|
||||
elif [ -s "$_tmp_file" ]; then
|
||||
log "Package '$p_name' conflicts with another package" "" "!>"
|
||||
log "Run 'KISS_CHOICE=1 kiss i $p_name' to add conflicts" "" "!>"
|
||||
die "as alternatives." "" "!>"
|
||||
@ -1082,6 +1110,7 @@ pkg_swap() {
|
||||
[ "$pkg_owns" ] || die "File '$2' exists on filesystem but isn't owned"
|
||||
|
||||
log "Swapping '$2' from '$pkg_owns' to '$1'"
|
||||
tmp_file "$pkg_owns" from-alt
|
||||
|
||||
# Convert the current owner to an alternative and rewrite its manifest
|
||||
# file to reflect this.
|
||||
@ -1096,15 +1125,17 @@ pkg_swap() {
|
||||
"$2") printf '%s\n' "${PWD#"$KISS_ROOT"}/$pkg_owns>${alt#*>}" ;;
|
||||
*) printf '%s\n' "$line" ;;
|
||||
esac
|
||||
done < "../installed/$pkg_owns/manifest" | sort -r > "$mak_dir/.$1"
|
||||
done < "../installed/$pkg_owns/manifest" | sort -r > "$_tmp_file"
|
||||
|
||||
mv -f "$mak_dir/.$1" "../installed/$pkg_owns/manifest"
|
||||
mv -f "$_tmp_file" "../installed/$pkg_owns/manifest"
|
||||
fi
|
||||
|
||||
# Convert the desired alternative to a real file and rewrite the manifest
|
||||
# file to reflect this. The reverse of above.
|
||||
mv -f "$alt" "$KISS_ROOT/$2"
|
||||
|
||||
tmp_file "$pkg_owns" to-alt
|
||||
|
||||
# Replace the matching line in the manifest with the desired replacement.
|
||||
# This used to be a 'sed' call which turned out to be a little error-prone
|
||||
# in some cases. This new method is a tad slower but ensures we never wipe
|
||||
@ -1114,9 +1145,9 @@ pkg_swap() {
|
||||
"${PWD#"$KISS_ROOT"}/$alt") printf '%s\n' "$2" ;;
|
||||
*) printf '%s\n' "$line" ;;
|
||||
esac
|
||||
done < "../installed/$1/manifest" | sort -r > "$mak_dir/.$1"
|
||||
done < "../installed/$1/manifest" | sort -r > "$_tmp_file"
|
||||
|
||||
mv -f "$mak_dir/.$1" "../installed/$1/manifest"
|
||||
mv -f "$_tmp_file" "../installed/$1/manifest"
|
||||
}
|
||||
|
||||
file_rwx() {
|
||||
@ -1196,7 +1227,7 @@ pkg_remove_files() {
|
||||
while read -r file; do
|
||||
case $file in /etc/?*[!/])
|
||||
sh256 "$KISS_ROOT/$file" >/dev/null
|
||||
sum_old=$(grep -F "${hash:-null}" "$mak_dir/c")
|
||||
sum_old=$(grep -F "${hash:-null}" "$1")
|
||||
|
||||
[ "${hash:-null}" = "$sum_old" ] || {
|
||||
printf 'Skipping %s (modified)\n' "$file"
|
||||
@ -1222,6 +1253,9 @@ pkg_remove_files() {
|
||||
fi
|
||||
done
|
||||
|
||||
# First argument needs to be dropped.
|
||||
shift
|
||||
|
||||
# Remove all broken directory symlinks.
|
||||
for sym do
|
||||
[ -e "$sym" ] || rm -f "$sym"
|
||||
@ -1229,9 +1263,9 @@ pkg_remove_files() {
|
||||
}
|
||||
|
||||
pkg_etc() (
|
||||
[ -d "$tar_dir/$pkg_name/etc" ] || return 0
|
||||
[ -d "$tar_dir/$1/etc" ] || return 0
|
||||
|
||||
cd "$tar_dir/$pkg_name"
|
||||
cd "$tar_dir/$1"
|
||||
|
||||
# Create all directories beforehand.
|
||||
find etc -type d | while read -r dir; do
|
||||
@ -1244,9 +1278,9 @@ pkg_etc() (
|
||||
|
||||
{ sh256 "$file"; sum_new=$hash
|
||||
sh256 "$KISS_ROOT/$file"; sum_sys=$hash
|
||||
sum_old=$(awk "NR == $i" "$mak_dir/c"); } >/dev/null 2>&1 || :
|
||||
sum_old=$(awk "NR == $i" "$2"); } >/dev/null 2>&1 || :
|
||||
|
||||
log "$pkg_name" "Doing 3-way handshake for $file"
|
||||
log "$1" "Doing 3-way handshake for $file"
|
||||
printf '%s\n' "Previous: ${sum_old:-null}"
|
||||
printf '%s\n' "System: ${sum_sys:-null}"
|
||||
printf '%s\n' "New: ${sum_new:-null}"
|
||||
@ -1272,7 +1306,7 @@ pkg_etc() (
|
||||
|
||||
# All other cases.
|
||||
*)
|
||||
war "$pkg_name" "saving /$file as /$file.new"
|
||||
war "$1" "saving /$file as /$file.new"
|
||||
new=.new
|
||||
;;
|
||||
esac
|
||||
@ -1317,11 +1351,11 @@ pkg_remove() {
|
||||
run_hook_pkg pre-remove "$1"
|
||||
run_hook pre-remove "$1" "$sys_db/$1"
|
||||
|
||||
# Make a backup of the etcsums file (if it exists).
|
||||
cp -f "$sys_db/$1/etcsums" "$mak_dir/c" 2>/dev/null || : > "$mak_dir/c"
|
||||
# Make a backup of any etcsums if they exist.
|
||||
tmp_file_copy "$pkg_name" etcsums-copy "$sys_db/$pkg_name/etcsums"
|
||||
|
||||
log "$1" "Removing package"
|
||||
pkg_remove_files < "$sys_db/$1/manifest"
|
||||
pkg_remove_files "$_tmp_file" < "$sys_db/$1/manifest"
|
||||
|
||||
# Reset 'trap' to its original value. Removal is done so
|
||||
# we no longer need to block 'Ctrl+C'.
|
||||
@ -1431,23 +1465,26 @@ pkg_install() {
|
||||
|
||||
log "$pkg_name" "Installing package (${tar_file##*/})"
|
||||
|
||||
# Make a backup of any etcsums if they exist.
|
||||
tmp_file_copy "$pkg_name" etcsums-copy "$sys_db/$pkg_name/etcsums"
|
||||
_etc_sums=$_tmp_file
|
||||
|
||||
# If the package is already installed (and this is an upgrade) make a
|
||||
# backup of the manifest and etcsums files.
|
||||
cp -f "$sys_db/$pkg_name/manifest" "$mak_dir/m" 2>/dev/null ||
|
||||
: > "$mak_dir/m"
|
||||
cp -f "$sys_db/$pkg_name/etcsums" "$mak_dir/c" 2>/dev/null ||
|
||||
: > "$mak_dir/c"
|
||||
tmp_file_copy "$pkg_name" manifest-copy "$sys_db/$pkg_name/manifest"
|
||||
tmp_file "$pkg_name" manifest-diff
|
||||
|
||||
tar_man=$tar_dir/$pkg_name/$pkg_db/$pkg_name/manifest
|
||||
|
||||
# Generate a list of files which exist in the currently installed manifest
|
||||
# but not in the newer (to be installed) manifest.
|
||||
grep -vFxf "$tar_man" "$_tmp_file_pre" > "$_tmp_file" 2>/dev/null ||:
|
||||
|
||||
# Reverse the manifest file so that we start shallow and go deeper as we
|
||||
# iterate over each item. This is needed so that directories are created
|
||||
# going down the tree.
|
||||
sort "$tar_man" > "$mak_dir/if"
|
||||
|
||||
# Generate a list of files which exist in the currently installed manifest
|
||||
# but not in the newer (to be installed) manifest.
|
||||
grep -vFxf "$tar_man" "$mak_dir/m" > "$mak_dir/rm" 2>/dev/null ||:
|
||||
tmp_file "$pkg_name" manifest-reverse
|
||||
sort "$tar_man" > "$_tmp_file"
|
||||
|
||||
# Block being able to abort the script with Ctrl+C during installation.
|
||||
# Removes all risk of the user aborting a package installation leaving
|
||||
@ -1456,7 +1493,7 @@ pkg_install() {
|
||||
|
||||
if
|
||||
# Install the package's files by iterating over its manifest.
|
||||
pkg_install_files -z "$tar_dir/$pkg_name" < "$mak_dir/if" &&
|
||||
pkg_install_files -z "$tar_dir/$pkg_name" < "$_tmp_file" &&
|
||||
|
||||
# Handle /etc/ files in a special way (via a 3-way checksum) to
|
||||
# determine how these files should be installed. Do we overwrite the
|
||||
@ -1465,16 +1502,16 @@ pkg_install() {
|
||||
#
|
||||
# This is more or less similar to Arch Linux's Pacman with the user
|
||||
# manually handling the .new files when and if they appear.
|
||||
pkg_etc &&
|
||||
pkg_etc "$pkg_name" "$_etc_sums" &&
|
||||
|
||||
# This is the aforementioned step removing any files from the old
|
||||
# version of the package if the installation is an update. Each file
|
||||
# type has to be specially handled to ensure no system breakage occurs.
|
||||
pkg_remove_files < "$mak_dir/rm" &&
|
||||
pkg_remove_files "$_etc_sums" < "$_tmp_file_pre" &&
|
||||
|
||||
# Install the package's files a second time to fix any mess caused by
|
||||
# the above removal of the previous version of the package.
|
||||
pkg_install_files -e "$tar_dir/$pkg_name" < "$mak_dir/if"
|
||||
pkg_install_files -e "$tar_dir/$pkg_name" < "$_tmp_file"
|
||||
|
||||
then
|
||||
# Reset 'trap' to its original value. Installation is done so we no longer
|
||||
|
Loading…
Reference in New Issue
Block a user