Это ошибка шифрования ZIP?

В развитие ответа @Gilles:

Действительно, set -e не работает внутри команд, если после них используется оператор ||, даже если вы запускаете их в подшивке; например, это не сработает:

#!/bin/sh

# prints:
#
# --> outer
# --> inner
# ./so_1.sh: line 16: some_failed_command: command not found
# <-- inner
# <-- outer

set -e

outer() {
  echo '--> outer'
  (inner) || {
    exit_code=$?
    echo '--> cleanup'
    return $exit_code
  }
  echo '<-- outer'
}

inner() {
  set -e
  echo '--> inner'
  some_failed_command
  echo '<-- inner'
}

outer

Но оператор || необходим для предотвращения возврата из внешней функции перед очисткой.

Есть небольшой трюк, который можно использовать, чтобы исправить это: запустите внутреннюю команду в фоновом режиме, а затем немедленно дождитесь ее выполнения. Встроенная функция wait вернет код выхода внутренней команды, и теперь вы используете || после wait, а не внутреннюю функцию, поэтому set -e корректно работает внутри последней:

#!/bin/sh

# prints:
#
# --> outer
# --> inner
# ./so_2.sh: line 27: some_failed_command: command not found
# --> cleanup

set -e

outer() {
  echo '--> outer'
  inner &
  wait $! || {
    exit_code=$?
    echo '--> cleanup'
    return $exit_code
  }
  echo '<-- outer'
}

inner() {
  set -e
  echo '--> inner'
  some_failed_command
  echo '<-- inner'
}

outer

Вот общая функция, основанная на этой идее. Она должна работать во всех POSIX-совместимых оболочках, если вы удалите ключевые слова local, т.е. заменить все local x=y на x=y:

# [CLEANUP=cleanup_cmd] run cmd [args...]
#
# `cmd` and `args...` A command to run and its arguments.
#
# `cleanup_cmd` A command that is called after cmd has exited,
# and gets passed the same arguments as cmd. Additionally, the
# following environment variables are available to that command:
#
# - `RUN_CMD` contains the `cmd` that was passed to `run`;
# - `RUN_EXIT_CODE` contains the exit code of the command.
#
# If `cleanup_cmd` is set, `run` will return the exit code of that
# command. Otherwise, it will return the exit code of `cmd`.
#
run() {
  local cmd="$1"; shift
  local exit_code=0

  local e_was_set=1; if ! is_shell_attribute_set e; then
    set -e
    e_was_set=0
  fi

  "$cmd" "$@" &

  wait $! || {
    exit_code=$?
  }

  if [ "$e_was_set" = 0 ] && is_shell_attribute_set e; then
    set +e
  fi

  if [ -n "$CLEANUP" ]; then
    RUN_CMD="$cmd" RUN_EXIT_CODE="$exit_code" "$CLEANUP" "$@"
    return $?
  fi

  return $exit_code
}


is_shell_attribute_set() { # attribute, like "x"
  case "$-" in
    *"$1"*) return 0 ;;
    *)    return 1 ;;
  esac
}

Пример использования:

#!/bin/sh
set -e

# Source the file with the definition of `run` (previous code snippet).
# Alternatively, you may paste that code directly here and comment the next line.
. ./utils.sh


main() {
  echo "--> main: $@"
  CLEANUP=cleanup run inner "$@"
  echo "<-- main"
}


inner() {
  echo "--> inner: $@"
  sleep 0.5; if [ "$1" = 'fail' ]; then
    oh_my_god_look_at_this
  fi
  echo "<-- inner"
}


cleanup() {
  echo "--> cleanup: $@"
  echo "    RUN_CMD = '$RUN_CMD'"
  echo "    RUN_EXIT_CODE = $RUN_EXIT_CODE"
  sleep 0.3
  echo '<-- cleanup'
  return $RUN_EXIT_CODE
}

main "$@"

Выполнение примера:

$ ./so_3 fail; echo "exit code: $?"

--> main: fail
--> inner: fail
./so_3: line 15: oh_my_god_look_at_this: command not found
--> cleanup: fail
    RUN_CMD = 'inner'
    RUN_EXIT_CODE = 127
<-- cleanup
exit code: 127

$ ./so_3 pass; echo "exit code: $?"

--> main: pass
--> inner: pass
<-- inner
--> cleanup: pass
    RUN_CMD = 'inner'
    RUN_EXIT_CODE = 0
<-- cleanup
<-- main
exit code: 0

Единственное, о чем вам нужно знать при использовании этого метода, это то, что все изменения переменных шелла, сделанные из команды, которую вы передаете в run, не распространятся на вызывающую функцию, потому что команда выполняется в подшелле.

13
18.12.2018, 21:42
1 ответ

Zip-архивы могут иметь несколько паролей для разных содержащихся файлов. Файлы внутри архива по существу независимы друг от друга -, они сжимаются без учета других файлов и шифруются таким же образом. Ваш encrypted.zipбудет иметь два (или более )зашифрованных сегмента, один с вашим исходным паролем, а другой с новым.

При попытке unzipфайл запросит оба пароля:

$ unzip../test.zip
Archive: ../test.zip
[../test.zip] file1 password:
  inflating: file1
  inflating: file2
[../test.zip] newfile password:
  inflating: newfile

Каталог, список имен файлов, не зашифрован. Это не ошибка,хотя это может сбивать с толку, и не все zip-инструменты хорошо справляются с ситуацией (, особенно графические инструменты ).

41
27.01.2020, 19:52

Теги

Похожие вопросы