deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
-
- 記事: 2092
- 登録日時: 15/10/25(日) 14:00
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
”タロ兵衛さんが書きました:
> 私の場合、sfsインストール後ではなく、sfs化する直前にsfs化用ディレクトリの./usr/share/applicationsにある.desktop を書き換えてしまってます。
それが正解だと思います。sfs をロードすると、*.desktop ファイルの内容が .jwmrc に反映されて jwm が再起動され、メニューが更新されます。
deb パッケージそのままでいいのなら自動変換が使えますが、修正が必要な場合は、結局手作業になります。とはいえ、元になるファイルが整えば、後は mksquashfs コマンドを実行するだけですが。
> 私の場合、sfsインストール後ではなく、sfs化する直前にsfs化用ディレクトリの./usr/share/applicationsにある.desktop を書き換えてしまってます。
それが正解だと思います。sfs をロードすると、*.desktop ファイルの内容が .jwmrc に反映されて jwm が再起動され、メニューが更新されます。
deb パッケージそのままでいいのなら自動変換が使えますが、修正が必要な場合は、結局手作業になります。とはいえ、元になるファイルが整えば、後は mksquashfs コマンドを実行するだけですが。
ThinkPad X121e (Precise 571 / Tahr 605 / Tahr64 606 / Xenial 7.5 / Bionic32)
CPU AMD C-50 1.0GHz, RAM 4GB
ThinkPad L440 (Xenial 7.5 / Bionic64 / Fossa64)
CPU intel Celeron 2950M 2.0GHz, RAM 4GB
CPU AMD C-50 1.0GHz, RAM 4GB
ThinkPad L440 (Xenial 7.5 / Bionic64 / Fossa64)
CPU intel Celeron 2950M 2.0GHz, RAM 4GB
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
deb2sfs.shの、sfs変換の動作とはあまり関係無い事ですが、不思議な事を見つけました。
SeaMonkey、Pale Moonで、「コード: 全て選択」でコピペして、スクリプトファイルを作成すると、行頭に半角スペース4文字が入ってしまいます。
理由は不明です。
Firefoxもそうだった様な記憶があるけれど、最近、使ってないので分かりません。
行頭の不要な空白文字を残したままでも、スクリプトの動作に問題はないはずだけど、一応、取り除いています。
Geany の置換で、正規表現を使って行頭の不要な空白を削除するのですが、deb2sfs.sh でやると、行頭の空白4文字だけでなく、インデント分の空白も削除されてしまいます。
つまり、正規表現を使わない、空白4文字だけでの置換になってしまいます。
使った正規表現は、
^xxxx x=半角スペース
分かりにくいですが、連続の半角スペースは一つにまとめられてしまうので。
初版がインデント空白3文字だったので気が付きませんでしたが、インデント空白4文字になった修正版で分かりました。
理由が分かるまで、しばらく悩みましたが。
現象が起こるのが、571JPのGeany(0.19.1)だけで、Tahrpup(1.25)、Xenialpup(1.29)のGeanyでは正規表現の置換が効きます。
571JPのGeanyのバージョンが古いからと言えば、それまでなのですが、面白いのが、Windowsで常用している VxEditor でも、置換で正規表現が効かずに同じ現象になる事です。
面倒なので、行頭空白は残したままでいいやと思いましたが、deb2sfs.sh では、不要な行頭空白を削除しないと、オプション -h でエラーが出て、ヘルプメッセージが表示されませんでした。
SeaMonkey、Pale Moonで、「コード: 全て選択」でコピペして、スクリプトファイルを作成すると、行頭に半角スペース4文字が入ってしまいます。
理由は不明です。
Firefoxもそうだった様な記憶があるけれど、最近、使ってないので分かりません。
行頭の不要な空白文字を残したままでも、スクリプトの動作に問題はないはずだけど、一応、取り除いています。
Geany の置換で、正規表現を使って行頭の不要な空白を削除するのですが、deb2sfs.sh でやると、行頭の空白4文字だけでなく、インデント分の空白も削除されてしまいます。
つまり、正規表現を使わない、空白4文字だけでの置換になってしまいます。
使った正規表現は、
^xxxx x=半角スペース
分かりにくいですが、連続の半角スペースは一つにまとめられてしまうので。
初版がインデント空白3文字だったので気が付きませんでしたが、インデント空白4文字になった修正版で分かりました。
理由が分かるまで、しばらく悩みましたが。
現象が起こるのが、571JPのGeany(0.19.1)だけで、Tahrpup(1.25)、Xenialpup(1.29)のGeanyでは正規表現の置換が効きます。
571JPのGeanyのバージョンが古いからと言えば、それまでなのですが、面白いのが、Windowsで常用している VxEditor でも、置換で正規表現が効かずに同じ現象になる事です。
面倒なので、行頭空白は残したままでいいやと思いましたが、deb2sfs.sh では、不要な行頭空白を削除しないと、オプション -h でエラーが出て、ヘルプメッセージが表示されませんでした。
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
少し機能を追加しました。マイナーのバージョンアップです。
以下の点を変更致しました。
コード: 全て選択
#!/usr/bin/env sh
## DebianパッケージをSquashFSに変換する
#
# @author ssnys
# @version 0.2.0
# @date 2018-06-28
# @licence https://creativecommons.org/licenses/by/4.0/
# @see http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372
deb2sfs () (
# shの設定
set -eu
# gettextの設定
TEXTDOMAIN='deb2sfs.sh'; export TEXTDOMAIN
# プログラム名
name='deb2sfs.sh'
# バージョン
version='0.2.0'
# 最終更新日
update='2018-06-28'
# ヘルプメッセージ
helpMessage=`cat <<EOF
\`gettext 'Usage'\`: ${0} [\`gettext 'options'\`] \`gettext 'dest'\` [\`gettext 'package1'\`] [\`gettext 'package2'\`] \`gettext '...'\`
\`gettext 'Convert Debian package to SquashFS.'\`
\`gettext 'Options'\`:
-c, --control \`gettext 'build Debian package control file'\`
-n, --no-sfs \`gettext 'do not make SquashFS but directory'\`
-o name[:value], --option=name[:value] \`gettext 'option of mksquashfs command'\`
-h, --help \`gettext 'display this help and exit'\`
-v, --verbose \`gettext 'enable verbose output'\`
-V, --version \`gettext 'output version information and exit'\`
\`gettext 'Support packages'\`: Debian package, Directory, SquashFS
\`gettext 'Example'\`:
${0} output.sfs *.deb
${0} -cv output.sfs *.deb
${0} -o b:1048576 -o comp:xz -o Xdict-size:100% output.sfs *.deb
${0} output.sfs 'http://www.example.com/example.deb'
\`gettext 'See'\`: <http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
EOF`
# バージョンメッセージ
versionMessage=`cat <<EOF
${name} version ${version} (update ${update})
\`gettext 'Licence'\`: CC-BY <https://creativecommons.org/licenses/by/4.0/>
\`gettext 'Using'\`: dpkg-deb, gettext, mksquashfs, sh, wget\`gettext ', etc.'\`
EOF`
# 変数を固定
readonly name version update helpMessage versionMessage
## 終了時に一時ディレクトリを削除する
endcall () {
[ -n "${verboseFlag-}" ] && translate '# Remove temporary directory and temporary file #'
rm -fr ${verboseFlag-} "${tmpDirectory}" "${tmpFile}"
}
## エラーメッセージを出力する
errorMessage () {
(
message="${2}"
shift 2
translate "%s: ${message}" "${0}" "${@}" 1>&2
translate "Try \`%s --help' for more information" "${0}" 1>&2
)
# EX_USAGE (/usr/include/sysexits.h)
exit "${1}"
}
## クォートをネストする
quote () {
echo "'`echo \"${1}\" | sed -re \"s/([']+)/'\\\"\1\\\"'/g\"`'"
}
## メッセージを翻訳する
translate () (
message="${1}"
shift
printf "`gettext \"${message}\"`\n" "${@}"
)
# 引数の解析
while [ 0 -lt "${#}" ]; do
case "${1}" in
# Debianパッケージのcontrol
'-c' | '--control')
controlFlag=1
shift
;;
# ヘルプメッセージ
'-h' | '--help')
echo "${helpMessage}"
return 0
;;
# SquashFSを作成しない
'-n' | '--no-sfs')
nosfsFlag=1
shift
;;
# mksquashfsのオプション
'-o' | '--option')
# オプションに引数がなかった場合
[ "${#}" -lt 2 ] && {
errorMessage 64 "option '%s' requires an argument" "${1}"
}
options="${options-} "`quote "-${2}" | sed -e "s/:/' '/"`
shift 2
;;
# 冗長な表示
'-v' | '--verbose')
verboseFlag='--verbose'
shift
;;
# バージョンメッセージ
'-V' | '--version')
echo "${versionMessage}"
return 0
;;
# 以降オプション以外の引数
'-' | '--')
shift
while [ 0 -lt "${#}" ]; do
parameters="${parameters-} "`quote "${1}"`
shift
done
;;
# ロングオプション
--[!-]*=*)
option="${1}"
shift
set -- "`echo \"${option}\" | cut -d '=' -f 1`" "`echo \"${option}\" | cut -d '=' -f 2-`" "${@}"
;;
# 複合ショートオプション
-[!-][!-]*)
option="${1}"
shift
set -- "-`echo \"${option}\" | cut -c 2`" "-`echo \"${option}\" | cut -c 3-`" "${@}"
;;
# 無効なオプション
-*)
errorMessage 64 "unrecognized option '%s'" "${1}"
;;
# オプション以外の引数
*)
parameters="${parameters-} "`quote "${1}"`
shift
# POSIX標準ならば以降オプション以外の引数
[ "`printenv 'POSIXLY_CORRECT' > /dev/null; echo \"${?}\"`" -eq 0 -o "`printenv 'ADSH_CMD_ARGORDER'`" = 'seq' ] && {
set -- '--' "${@}"
}
;;
esac
done
# 変数を固定
readonly controlFlag nosfsFlag options parameters verboseFlag
# オプション以外の引数の存在を確認
[ -z "${parameters-}" ] && {
errorMessage 64 'missing arguments'
}
# 位置パラメータを再セット
eval "set ${parameters-}"
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
[ -n "${verboseFlag-}" ] && translate '# Make temporary directory and temporary file #'
tmpDirectory=`mktemp -d`
tmpFile=`mktemp`
# 終了時に関数を呼び出す
trap "endcall" EXIT
trap "endcall; exit 129" 1
trap "endcall; exit 130" 2
trap "endcall; exit 131" 3
trap "endcall; exit 143" 15
# 変数を固定
readonly dest tmpDirectory tmpFile
# ${controlFlag}が有効ならば/etc/init.dを作成
[ "${controlFlag-0}" -eq 1 ] && {
initd="${tmpDirectory}/etc/init.d"
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' '/etc/init.d'
mkdir -p ${verboseFlag-} "${initd}"
}
# 各パッケージを処理
for package; do
# URLならばタウンロード
`echo "${package}" | grep -qE '^https?://|^ftps?://'` && {
[ -n "${verboseFlag-}" ] && translate '# Download %s #' "${package}"
wget -nv ${verboseFlag-} -O "${tmpFile}" "${package}"
package="${tmpFile}"
}
# パッケージの種類によって処理を分岐
case `file -bL "${package}"` in
# Debianパッケージ
'Debian binary package'*)
# Debianパッケージからファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract files in %s #' "${package}"
dpkg-deb ${verboseFlag-} -x "${package}" "${tmpDirectory}"
# ${controlFlag}による処理の分岐
[ "${controlFlag-0}" -eq 1 ] && {
debname=`dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}' "${package}"`
control="${tmpDirectory}/var/run/deb2sfs.sh/${debname}"
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' "/var/run/deb2sfs.sh/${debname}"
mkdir -p ${verboseFlag-} "${control}"
# Debianパッケージからコントロールファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract control files in %s #' "${package}"
dpkg-deb ${verboseFlag-} -e "${package}" "${control}"
# サービス起動スクリプトを作成
cat > "${initd}/${debname}.sh" <<EOF
#!/usr/bin/env sh
set -eu
control="/var/run/deb2sfs.sh/${debname}"
readonly control
case "\${1}" in
'start')
[ -x "\${control}/preinst" ] && "\${control}/preinst" 'install'
[ -x "\${control}/postinst" ] && "\${control}/postinst" 'configure' "\`grep -m 1 '^Version:' \"\${control}/control\" | sed -e 's/^Version:[ ]*//'\`"
;;
'stop')
[ -x "\${control}/prerm" ] && "\${control}/prerm" 'remove'
[ -x "\${control}/postrm" ] && "\${control}/postrm" 'remove'
;;
esac
EOF
[ -n "${verboseFlag-}" ] && translate '# Chenge mod %s #' "/etc/init.d/${debname}.sh"
chmod ${verboseFlag-} 755 "${initd}/${debname}.sh"
}
;;
# ディレクトリ
'directory')
[ -n "${verboseFlag-}" ] && translate '# Copy files in %s #' "${package}"
cp -afT ${verboseFlag-} "${package}" "${tmpDirectory}"
;;
# SquashFS
'Squashfs filesystem'*)
if [ -z "${verboseFlag-}" ]; then
unsquashfs -d "${tmpDirectory}" -f "${package}" > /dev/null
else
translate '# Extract files in %s #' "${package}"
unsquashfs -d "${tmpDirectory}" -f "${package}"
fi
;;
# それ以外
*)
errorMessage 65 '%s is an unsupported file format' "${package}"
;;
esac
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
[ -d "${tmpDirectory}${path}" ] && {
[ -n "${verboseFlag-}" ] && translate '# Move %s #' "${path}"
cp -afT ${verboseFlag-} "${tmpDirectory}${path}" "${tmpDirectory}${path}/.."
rm -fr ${verboseFlag-} "${tmpDirectory}${path}"
}
done
# ${nosfsFlag}による処理の分岐
if [ "${nosfsFlag-0}" -eq 1 ]; then
# 一時ディレクトリの内容をコピー
[ -n "${verboseFlag-}" ] && translate '# Copy temporary directory to %s #' "${dest}"
cp -afT ${verboseFlag-} "${tmpDirectory}" "${dest}"
else
# SquashFSの作成
[ -n "${verboseFlag-}" ] && translate '# Make %s #' "${dest}"
eval "mksquashfs \"${tmpDirectory}\" \"${dest}\" ${options-}"
fi
)
# メインの関数を呼び出す
deb2sfs "${@}"
- ディレクトリやSquashFSに対応
- 内部関数errorMessageで終了ステータスを指定可能に
- gettextに渡すエラーメッセージを修正
コード: 全て選択
deb2sfs.sh new-a-b-c.sfs a-b-c.sfs a.deb
`dpkg-deb -x`で解凍は可能なようですが、変換できないというのは摩訶不思議ですね。当方もまだ調査できていないため、何とも言えませんが、やはり空き容量不足なのでしょうか。ルビー さんが書きました:VirtualBoxの571JPで、slimjet_i386.deb(59MB)を dpkg-deb -x で解凍可能な状態でも、sfs変換に失敗しました。ssnys さんが書きました: slimjetのDebianパッケージを解凍しても問題ない十分なディスクスペースがあると仮定して、以下のようなコマンドで解凍できませんか?
pupsaveの中(/root/~)、外(/mnt/home/~/)で試しましたが、同じ結果です。
ちなみに、pupsave 256MB では、空き不足になって解凍不可でした。
VirtualBoxのXenialpupでも、slimjet_i386.debのsfs変換を試してみましたが失敗。
そこで、R40(RAM256MB)の571JPで試してみると、同様のエラーメッセージで失敗しました。
VirtualBoxのRAMは 896MB なのですが、もしかして、これでは足りないのかもしれません。
変換に成功した901XのRAMは 1GB です。
901Xの571JPでは、pupsave(256MB)の空き不足で失敗するだろうと思って試したのですけど、あっさり成功しました。
SDHCカードにインストールしてあるpupsaveの書き込みは、ハードディスクにインストールした場合と違うので、その為だと思いますが、RAMは 1GB あるので成功したのかな。
大きなサイズのdebパッケージのsfs変換では、大きめのRAMがないと無理かもしれない。
thinkpadnerdさんの仰る通り変換に最低でも「deb パッケージのサイズ + deb を展開したファイルのサイズ + sfs のサイズ 」の容量が必要です。パッケージから展開されたファイルなどは、スクリプト終了時に削除されるまで、`mktemp`コマンドで作成した一時ディレクトリ($TMPDIRが設定されていれば$TMPDIRが使用され、 設定されていなければ /tmp内に作成)に置かれます。作成した一時ディレクトリの場所のファイルシステムが何であるかによるのですが、tmpfsの場合、パッケージをメモリー上に展開するため、十分なメモリー容量が必要かと思われます。もしかしたらここら辺が関係しているのかもしれません。thinkpadnerd さんが書きました: deb パッケージのサイズ + deb を展開したファイルのサイズ + sfs のサイズ + α
が必要だと思いますが、展開の途中でスペースがなくなるというのはどういうことでしょうね。私は puppy がインストールされているパーティションが NTFS なので、別に ext2 のパーティションを用意して作業しています。
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
機能もほとんど変わらない、小幅な修正を行いました。
以前のバージョンからの変更点は以下の様になります。
コード: 全て選択
#!/usr/bin/env sh
## DebianパッケージをSquashFSに変換する
#
# @author ssnys
# @version 0.2.1
# @date 2018-07-07
# @licence https://creativecommons.org/licenses/by/4.0/
# @see http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372
deb2sfs () (
# shの設定
set -eu
# gettextの設定
TEXTDOMAIN='deb2sfs.sh'; export TEXTDOMAIN
# プログラム名
name='deb2sfs.sh'
# バージョン
version='0.2.1'
# 最終更新日
update='2018-07-07'
# ヘルプメッセージ
helpMessage=`cat <<EOF
\`gettext 'Usage'\`: ${0} [\`gettext 'options'\`] \`gettext 'dest'\` [\`gettext 'package1'\`] [\`gettext 'package2'\`] \`gettext '...'\`
\`gettext 'Convert Debian package to SquashFS.'\`
\`gettext 'Options'\`:
-c, --control \`gettext 'build Debian package control file'\`
-n, --no-sfs \`gettext 'do not make SquashFS but directory'\`
-o name[:value], --option=name[:value] \`gettext 'option of mksquashfs command'\`
-h, --help \`gettext 'display this help and exit'\`
-v, --verbose \`gettext 'enable verbose output'\`
-V, --version \`gettext 'output version information and exit'\`
-, -- \`gettext 'stop option parsing'\`
\`gettext 'Support packages'\`: Debian package, Directory, SquashFS
\`gettext 'Example'\`:
${0} output.sfs *.deb
${0} -cv output.sfs *.deb
${0} -o b:1048576 -o comp:xz -o Xdict-size:100% output.sfs *.deb
${0} output.sfs 'http://www.example.com/example_1.0.0_i386.deb'
\`gettext 'See'\`: <http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
EOF`
# バージョンメッセージ
versionMessage=`cat <<EOF
${name} version ${version} (update ${update})
\`gettext 'Licence'\`: CC-BY <https://creativecommons.org/licenses/by/4.0/>
\`gettext 'Using'\`: dpkg-deb, gettext, mksquashfs, sh, wget\`gettext ', etc.'\`
EOF`
# 変数を固定
readonly name version update helpMessage versionMessage
## 終了時に一時ディレクトリを削除する
endcall () {
[ -n "${verboseFlag-}" ] && translate '# Remove temporary directory and temporary file #'
rm -fr ${verboseFlag-} "${tmpDirectory}" "${tmpFile}"
}
## エラーメッセージを出力して終了する
errorMessage () {
(
message="${2}"
shift 2
translate "%s: ${message}" "${0}" ${@+"$@"} 1>&2
translate "Try \`%s --help' for more information" "${0}" 1>&2
)
exit "${1}"
}
## クォートをネストする
quote () {
echo "'`echo \"${1}\" | sed -re \"s/([']+)/'\\\"\1\\\"'/g\"`'"
}
## メッセージを翻訳する
translate () (
message="${1}"
shift
printf "`gettext \"${message}\"`\n" ${@+"$@"}
)
# 引数の解析
while [ 0 -lt "${#}" ]; do
case "${1}" in
# Debianパッケージのcontrol
'-c' | '--control')
controlFlag=1
shift
;;
# ヘルプメッセージ
'-h' | '--help')
echo "${helpMessage}"
return 0
;;
# SquashFSを作成しない
'-n' | '--no-sfs')
nosfsFlag=1
shift
;;
# mksquashfsのオプション
'-o' | '--option')
# オプションに引数がなかった場合
[ "${#}" -lt 2 ] && {
errorMessage 64 "option '%s' requires an argument" "${1}"
}
options="${options-} "`quote "-${2}" | sed -e "s/:/' '/"`
shift 2
;;
# 冗長な表示
'-v' | '--verbose')
verboseFlag='--verbose'
shift
;;
# バージョンメッセージ
'-V' | '--version')
echo "${versionMessage}"
return 0
;;
# 以降オプション以外の引数
'-' | '--')
shift
while [ 0 -lt "${#}" ]; do
parameters="${parameters-} "`quote "${1}"`
shift
done
;;
# ロングオプション
--[!-]*=*)
option="${1}"
shift
set -- "`echo \"${option}\" | cut -d '=' -f 1`" "`echo \"${option}\" | cut -d '=' -f 2-`" ${@+"$@"}
;;
# 複合ショートオプション
-[!-][!-]*)
option="${1}"
shift
set -- "-`echo \"${option}\" | cut -c 2`" "-`echo \"${option}\" | cut -c 3-`" ${@+"$@"}
;;
# 無効なオプション
-*)
errorMessage 64 "unrecognized option '%s'" "${1}"
;;
# オプション以外の引数
*)
parameters="${parameters-} "`quote "${1}"`
shift
# POSIX標準ならば以降オプション以外の引数
[ "`printenv 'POSIXLY_CORRECT' > /dev/null; echo \"${?}\"`" -eq 0 -o "`printenv 'ADSH_CMD_ARGORDER'`" = 'seq' ] && {
set -- '--' ${@+"$@"}
}
;;
esac
done
# 変数を固定
readonly controlFlag nosfsFlag options parameters verboseFlag
# オプション以外の引数の存在を確認
[ -z "${parameters-}" ] && {
errorMessage 64 'missing arguments'
}
# 位置パラメータを再セット
eval "set ${parameters-}"
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
[ -n "${verboseFlag-}" ] && translate '# Make temporary directory and temporary file #'
tmpDirectory=`mktemp -d`
tmpFile=`mktemp`
initd="${tmpDirectory}/etc/init.d"
# 変数を固定
readonly dest tmpDirectory tmpFile initd
# 終了時に関数を呼び出す
trap 'endcall' 0 # EXIT
trap 'endcall; exit 129' 1 # SIGHUP
trap 'endcall; exit 130' 2 # SIGINT
trap 'endcall; exit 131' 3 # SIGQUIT
trap 'endcall; exit 143' 15 # SIGTERM
# 各パッケージを処理
for package; do
# URLならばタウンロード
`echo "${package}" | grep -qE '^https?://|^ftps?://'` && {
[ -n "${verboseFlag-}" ] && translate '# Download %s #' "${package}"
wget -nv ${verboseFlag-} -O "${tmpFile}" "${package}"
package="${tmpFile}"
}
# パッケージの種類によって処理を分岐
case `file -bL "${package}"` in
# Debianパッケージ
'Debian binary package'*)
# Debianパッケージからファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract files in %s #' "${package}"
dpkg-deb ${verboseFlag-} -x "${package}" "${tmpDirectory}"
# ${controlFlag}による処理の分岐
[ "${controlFlag-0}" -eq 1 ] && {
debname=`dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}.deb' "${package}"`
control="${tmpDirectory}/var/run/deb2sfs.sh/${debname}"
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' "/var/run/deb2sfs.sh/${debname}"
mkdir -p ${verboseFlag-} "${control}"
# Debianパッケージからコントロールファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract control files in %s #' "${package}"
dpkg-deb ${verboseFlag-} -e "${package}" "${control}"
# スクリプトの有無により処理を分岐
[ -x "${control}/preinst" -o -x "${control}/postinst" -o -x "${control}/prerm" -o -x "${control}/postrm" ] && {
# /etc/init.dを作成
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' '/etc/init.d'
mkdir -p ${verboseFlag-} "${initd}"
# サービス起動スクリプトを作成
cat > "${initd}/${debname}.sh" <<EOF
#!/usr/bin/env sh
## Startup ${debname} maintainer scripts
#
# @date `date '+%Y-%m-%d'`
# @note Automatically generated by ${name} version ${version} (update ${update})
set -eu
control="/var/run/deb2sfs.sh/${debname}"
readonly control
case "\${1}" in
'start')
[ -x "\${control}/preinst" ] && "\${control}/preinst" 'install'
[ -x "\${control}/postinst" ] && "\${control}/postinst" 'configure' "\`grep -m 1 '^Version:' \"\${control}/control\" | sed -re 's/^Version:[[:blank:]]*([^[:blank:]]+)[[:blank:]]*$/\1/'\`"
;;
'stop')
[ -x "\${control}/prerm" ] && "\${control}/prerm" 'remove'
[ -x "\${control}/postrm" ] && "\${control}/postrm" 'remove'
;;
'restart')
shift
"\${0}" 'stop' \${@+"\$@"}
"\${0}" 'start' \${@+"\$@"}
;;
*)
echo "Usage: \${0} {start|stop|restart}" 1>&2
# EX_USAGE (/usr/include/sysexits.h)
exit 64
;;
esac
EOF
[ -n "${verboseFlag-}" ] && translate '# Chenge mod %s #' "/etc/init.d/${debname}.sh"
chmod ${verboseFlag-} 755 "${initd}/${debname}.sh"
}
}
;;
# ディレクトリ
'directory')
[ -n "${verboseFlag-}" ] && translate '# Copy files in %s #' "${package}"
cp -afT ${verboseFlag-} "${package}" "${tmpDirectory}"
;;
# SquashFS
'Squashfs filesystem'*)
if [ -z "${verboseFlag-}" ]; then
unsquashfs -d "${tmpDirectory}" -f "${package}" > /dev/null
else
translate '# Extract files in %s #' "${package}"
unsquashfs -d "${tmpDirectory}" -f "${package}"
fi
;;
# それ以外
*)
errorMessage 65 '%s is an unsupported file format' "${package}"
;;
esac
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
[ -d "${tmpDirectory}${path}" ] && {
[ -n "${verboseFlag-}" ] && translate '# Move %s #' "${path}"
cp -afT ${verboseFlag-} "${tmpDirectory}${path}" "${tmpDirectory}${path}/.."
rm -fr ${verboseFlag-} "${tmpDirectory}${path}"
}
done
# ${nosfsFlag}による処理の分岐
if [ "${nosfsFlag-0}" -eq 1 ]; then
# 一時ディレクトリの内容をコピー
[ -n "${verboseFlag-}" ] && translate '# Copy temporary directory to %s #' "${dest}"
cp -afT ${verboseFlag-} "${tmpDirectory}" "${dest}"
else
# SquashFSの作成
[ -n "${verboseFlag-}" ] && translate '# Make %s #' "${dest}"
eval "mksquashfs \"${tmpDirectory}\" \"${dest}\" ${options-}"
fi
)
# メインの関数を呼び出す
deb2sfs ${@+"$@"}
- ヘルプメッセージを修正しました
- 様々なシェルに対応できるよう、"${@}"を${@+"$@"}に変更しました
- preinst, postinst, prerm, postrmの何れも存在しない場合、サービス起動スクリプトを作成しないようになりました
- サービス起動スクリプトの内容をより詳細にしました
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
大幅なバージョンアップを行いました。
以前のバージョンからの変更点は以下の様になります。
コード: 全て選択
#!/usr/bin/env sh
## パッケージをSquashFSに変換する
#
# @author ssnys
# @version 1.0.0
# @date 2018-07-23
# @licence https://creativecommons.org/licenses/by/4.0/
# @see http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372
package2sfs () (
# shの設定
set -eu
# gettextの設定
TEXTDOMAIN='package2sfs.sh'; export TEXTDOMAIN
# プログラム名
name='package2sfs.sh'
# バージョン
version='1.0.0'
# 最終更新日
update='2018-07-23'
# ヘルプメッセージ
helpMessage=`cat <<EOF
\`gettext 'Usage'\`: ${0} [\`gettext 'options'\`] \`gettext 'dest'\` [\`gettext 'package1'\`] [\`gettext 'package2'\`] \`gettext '...'\`
\`gettext 'Convert package to SquashFS.'\`
\`gettext 'Options'\`:
-c, --control \`gettext 'build package control file'\`
-n, --no-sfs \`gettext 'do not make SquashFS but directory'\`
-o name[:value], --option=name[:value] \`gettext 'option of mksquashfs command'\`
-h, --help \`gettext 'display this help and exit'\`
-v, --verbose \`gettext 'enable verbose output'\`
-V, --version \`gettext 'output version information and exit'\`
-, -- \`gettext 'stop option parsing'\`
\`gettext 'Support packages'\`: Debian package, Directory, Image file(ext2, ext3, ext4), Puppy's Extra Treats, SquashFS, tar.gz, tar.xz
\`gettext 'Example'\`:
${0} output.sfs *.deb
${0} -cv output.sfs *.deb
${0} -o b:1048576 -o comp:xz -o Xdict-size:100% output.sfs *.deb
${0} output.sfs 'http://www.example.com/example_1.0.0_i386.deb'
\`gettext 'See'\`: <http://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
EOF`
# バージョンメッセージ
versionMessage=`cat <<EOF
${name} version ${version} (update ${update})
\`gettext 'Licence'\`: CC-BY <https://creativecommons.org/licenses/by/4.0/>
\`gettext 'Using'\`: dpkg-deb, gettext, mksquashfs, pet2tgz, tar, unsquashfs, wget\`gettext ', etc.'\`
EOF`
# 変数を固定
readonly name version update helpMessage versionMessage
## Debianパッケージを展開する
deb2dir () {
# Debianパッケージからファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract files in %s #' "${1}"
dpkg-deb ${verboseFlag-} -x "${1}" "${2}"
# ${controlFlag}による処理の分岐
[ "${controlFlag-0}" -eq 1 ] && {
filename=`dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}.deb' "${1}"`
control="${2}/var/run/${name}/${filename}"
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' "/var/run/${name}/${filename}"
mkdir -p ${verboseFlag-} "${control}"
# Debianパッケージからコントロールファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract control files in %s #' "${1}"
dpkg-deb ${verboseFlag-} -e "${1}" "${control}"
# スクリプトの有無により処理を分岐
[ -x "${control}/preinst" -o -x "${control}/postinst" -o -x "${control}/prerm" -o -x "${control}/postrm" ] && startupScript "${2}" "${filename}" "`cat <<'EOF'
'start')
[ -x \"${control}/preinst\" ] && \"${control}/preinst\" 'install'
[ -x \"${control}/postinst\" ] && \"${control}/postinst\" 'configure' \"\`grep -m 1 '^Version:' \\"${control}/control\\" | sed -re 's/^Version:[[:blank:]]*([^[:blank:]]+)[[:blank:]]*$/\1/'\`\"
;;
'stop')
[ -x \"${control}/prerm\" ] && \"${control}/prerm\" 'remove'
[ -x \"${control}/postrm\" ] && \"${control}/postrm\" 'remove'
;;
EOF`"
}
return 0
}
## 終了時に一時ディレクトリを削除する
endcall () {
[ -n "${verboseFlag-}" ] && translate '# Remove temporary directory and temporary file #'
rm -fr ${verboseFlag-} "${tmpDirectory}"
}
## エラーメッセージを出力して終了する
errorMessage () {
(
message="${2}"
shift 2
translate "%s: ${message}" "${0}" ${@+"$@"} 1>&2
translate "Try \`%s --help' for more information" "${0}" 1>&2
)
exit "${1}"
}
## Puppy's Extra Treatsパッケージを展開する
pet2dir () {
bname=`basename "${package}" '.pet'`
tmpPet=`mktemp -d`
cp -af ${verboseFlag-} "${1}" "${tmpPet}/package.pet"
pet2tgz "${tmpPet}/package.pet"
# 圧縮ファイルからファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract files in %s #' "${1}"
tar -C "${2}" -f "${tmpPet}/package.tar.gz" -xz ${verboseFlag-}
[ -d "${2}/${bname}" ] && {
cp -afT "${2}/${bname}" "${2}"
rm -fr ${verboseFlag-} "${2}/${bname}"
}
rm -fr ${verboseFlag-} "${tmpPet}"
# ${controlFlag}による処理の分岐
[ -x "${2}/pinstall.sh" -o -x "${2}/puninstall.sh" -o -f "${2}/pet.specs" ] && {
[ "${controlFlag-0}" -eq 1 ] && {
filename=`basename "${package}"`
# スクリプトの有無により処理を分岐
[ -x "${2}/pinstall.sh" -o -x "${2}/puninstall.sh" ] && startupScript "${2}" "${filename}" "`cat <<'EOF'
'start')
[ -x \"${control}/pinstall.sh\" ] && \"${control}/pinstall.sh\"
;;
'stop')
[ -x \"${control}/puninstall.sh\" ] && \"${control}/puninstall.sh\"
;;
EOF`"
[ -n "${verboseFlag-}" ] && translate '# Move %s files #' '/pinstall.sh, /puninstall.sh, /pet.specs'
mkdir -p ${verboseFlag-} "${2}/var/run/${name}/${filename}"
cp -af ${verboseFlag-}\
`[ -x "${2}/pinstall.sh" ] && echo "${2}/pinstall.sh"`\
`[ -x "${2}/puninstall.sh" ] && echo "${2}/puninstall.sh"`\
`[ -f "${2}/pet.specs" ] && echo "${2}/pet.specs"`\
"${2}/var/run/${name}/${filename}"
}
rm -fr ${verboseFlag-} "${2}/pinstall.sh" "${2}/puinstall.sh" "${2}/pet.specs"
}
return 0
}
## Slackwareパッケージを展開する
pkg2dir () {
`file -bL "${1}" | grep -Eq '^xz compressed data'` && tarOption='-J'
# 圧縮ファイルからファイルを取り出す
[ -n "${verboseFlag-}" ] && translate '# Extract files in %s #' "${1}"
tar -C "${2}" -f "${1}" -x "${tarOption--z}" ${verboseFlag-}
# ${controlFlag}による処理の分岐
[ -d "${2}/install" ] && {
[ "${controlFlag-0}" -eq 1 ] && {
filename=`basename "${1}"`
# スクリプトの有無により処理を分岐
[ -f "${2}/install/doinst.sh" ] && {
chmod ${verboseFlag-} 755 "${2}/install/doinst.sh"
startupScript "${2}" "${filename}" "`cat <<'EOF'
'start')
[ -x \"${control}/doinst.sh\" ] && \"${control}/doinst.sh\"
;;
'stop')
;;
EOF`"
}
[ -n "${verboseFlag-}" ] && translate '# Move %s directory #' '/install'
mkdir -p ${verboseFlag-} "${2}/var/run/${name}/${filename}"
cp -afT ${verboseFlag-} "${2}/install" "${2}/var/run/${name}/${filename}"
}
rm -fr ${verboseFlag-} "${2}/install"
}
return 0
}
## クォートをネストする
quote () (
echo "'`echo \"${1}\" | sed -re \"s/([']+)/'\\\"\1\\\"'/g\"`'"
)
## サービス起動スクリプトを作成する
startupScript () {
# /etc/init.dを作成
[ -n "${verboseFlag-}" ] && translate '# Make %s directory #' '/etc/init.d'
mkdir -p ${verboseFlag-} "${1}/etc/init.d"
# サービス起動スクリプトを作成
cat > "${1}/etc/init.d/${2}.sh" <<EOF
#!/usr/bin/env sh
## Startup ${2} maintainer scripts
#
# @date `date '+%Y-%m-%d'`
# @note Automatically generated by ${name} version ${version} (update ${update})
set -eu
control="/var/run/${name}/${2}"
readonly control
cd /
case "\${1}" in
${3}
'restart')
shift
"\${0}" 'stop' \${@+"\$@"}
"\${0}" 'start' \${@+"\$@"}
;;
*)
echo "Usage: \${0} {start|stop|restart}" 1>&2
# EX_USAGE (/usr/include/sysexits.h)
exit 64
;;
esac
EOF
# パーミッションを変更し実行可能に
[ -n "${verboseFlag-}" ] && translate '# Chenge mod %s #' "/etc/init.d/${2}.sh"
chmod ${verboseFlag-} 755 "${1}/etc/init.d/${2}.sh"
}
## メッセージを翻訳する
translate () (
message="${1}"
shift
printf "`gettext \"${message}\"`\n" ${@+"$@"}
)
# 引数の解析
while [ 0 -lt "${#}" ]; do
case "${1}" in
# パッケージのcontrol
'-c' | '--control')
controlFlag=1
shift
;;
# ヘルプメッセージ
'-h' | '--help')
echo "${helpMessage}"
return 0
;;
# SquashFSを作成しない
'-n' | '--no-sfs')
nosfsFlag=1
shift
;;
# mksquashfsのオプション
'-o' | '--option')
# オプションに引数がなかった場合
[ "${#}" -lt 2 ] && {
errorMessage 64 "option '%s' requires an argument" "${1}"
}
options="${options-} "`quote "-${2}" | sed -e "s/:/' '/"`
shift 2
;;
# 冗長な表示
'-v' | '--verbose')
verboseFlag='--verbose'
shift
;;
# バージョンメッセージ
'-V' | '--version')
echo "${versionMessage}"
return 0
;;
# 以降オプション以外の引数
'-' | '--')
shift
while [ 0 -lt "${#}" ]; do
parameters="${parameters-} "`quote "${1}"`
shift
done
;;
# ロングオプション
--[!-]*=*)
option="${1}"
shift
set -- "`echo \"${option}\" | cut -d '=' -f 1`" "`echo \"${option}\" | cut -d '=' -f 2-`" ${@+"$@"}
;;
# 複合ショートオプション
-[!-][!-]*)
option="${1}"
shift
set -- "-`echo \"${option}\" | cut -c 2`" "-`echo \"${option}\" | cut -c 3-`" ${@+"$@"}
;;
# 無効なオプション
-*)
errorMessage 64 "unrecognized option '%s'" "${1}"
;;
# オプション以外の引数
*)
parameters="${parameters-} "`quote "${1}"`
shift
# POSIX標準ならば以降オプション以外の引数
[ "`printenv 'POSIXLY_CORRECT' > /dev/null; echo \"${?}\"`" -eq 0 -o "`printenv 'ADSH_CMD_ARGORDER'`" = 'seq' ] && {
set -- '--' ${@+"$@"}
}
;;
esac
done
# 変数を固定
readonly controlFlag nosfsFlag options parameters verboseFlag
# オプション以外の引数の存在を確認
[ -z "${parameters-}" ] && {
errorMessage 64 'missing arguments'
}
# 位置パラメータを再セット
eval "set ${parameters-}"
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
[ -n "${verboseFlag-}" ] && translate '# Make temporary directory and temporary file #'
tmpDirectory=`mktemp -d`
tmpContent="${tmpDirectory}/content"
tmpDownload="${tmpDirectory}/download"
tmpPackage="${tmpDirectory}/package"
mkdir -p ${verboseFlag-} "${tmpContent}" "${tmpPackage}"
# 変数を固定
readonly dest tmpDirectory tmpContent tmpDownload tmpPackage
# 終了時に関数を呼び出す
trap 'endcall' 0 # EXIT
trap 'exit 129' 1 # SIGHUP
trap 'exit 130' 2 # SIGINT
trap 'exit 131' 3 # SIGQUIT
trap 'exit 143' 15 # SIGTERM
# 各パッケージを処理
for package; do
# URLならばタウンロード
`echo "${package}" | grep -qE '^https?://|^ftps?://'` && {
filename=`basename "${package}"`
[ -n "${verboseFlag-}" ] && translate '# Download %s #' "${package}"
wget -nv -O "${tmpDownload}/${filename}" ${verboseFlag-} "${package}"
package="${tmpDownload}/${filename}"
}
# パッケージの種類によって処理を分岐
case `file -bL "${package}"` in
# Debianパッケージ
'Debian binary package'*)
deb2dir "${package}" "${tmpContent}"
;;
# ディレクトリ
'directory')
[ -n "${verboseFlag-}" ] && translate '# Copy files in %s #' "${package}"
cp -afT ${verboseFlag-} "${package}" "${tmpContent}"
;;
# Slackware GZIP or Puppy's Extra Treats
'gzip compressed data'*)
if `echo "${package}" | grep -qE '\.pet$'`; then
pet2dir "${package}" "${tmpPackage}"
else
pkg2dir "${package}" "${tmpPackage}"
fi
;;
# Image file (ext2, ext3, ext4)
'Linux rev 1.0 ext'[2-4]' filesystem data'*)
loopDevice=`losetup -f`
[ -n "${verboseFlag-}" ] && translate '# Mount %s #' "${package}"
losetup -r "${loopDevice}" "${package}"
mount -o 'defaults' -r ${verboseFlag:+-v} "${loopDevice}" "${tmpPackage}"
[ -n "${verboseFlag-}" ] && translate '# Copy files in %s #' "${package}"
cp -afT ${verboseFlag-} "${tmpPackage}" "${tmpContent}"
[ -n "${verboseFlag-}" ] && translate '# Unmount %s #' "${package}"
umount -d ${verboseFlag:+-v} "${tmpPackage}"
;;
# SquashFS
'Squashfs filesystem'*)
if [ -z "${verboseFlag-}" ]; then
unsquashfs -d "${tmpContent}" -f "${package}" > /dev/null
else
translate '# Extract files in %s #' "${package}"
unsquashfs -d "${tmpContent}" -f "${package}"
fi
;;
# Slackware XZ
'xz compressed data'*)
pkg2dir "${package}" "${tmpPackage}"
;;
# それ以外
*)
errorMessage 65 '%s is an unsupported file format' "${package}"
;;
esac
# 解凍したファイルをメインのディレクトリに移動
cp -afT ${verboseFlag-} "${tmpPackage}" "${tmpContent}"
rm -fr ${verboseFlag-} "${tmpPackage}"/* "${tmpPackage}"/.[!.]* "${tmpPackage}"/..?*
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
[ -d "${tmpContent}${path}" ] && {
[ -n "${verboseFlag-}" ] && translate '# Move %s #' "${path}"
cp -afT ${verboseFlag-} "${tmpContent}${path}" "${tmpContent}${path}/.."
rm -fr ${verboseFlag-} "${tmpContent}${path}"
}
done
# ${nosfsFlag}による処理の分岐
if [ "${nosfsFlag-0}" -eq 1 ]; then
# 一時ディレクトリの内容をコピー
[ -n "${verboseFlag-}" ] && translate '# Copy temporary directory to %s #' "${dest}"
cp -afT ${verboseFlag-} "${tmpContent}" "${dest}"
else
# SquashFSの作成
[ -n "${verboseFlag-}" ] && translate '# Make %s #' "${dest}"
eval "mksquashfs \"${tmpContent}\" \"${dest}\" ${options-}"
fi
)
# メインの関数を呼び出す
package2sfs ${@+"$@"}
- Slackwareのパッケージ(tgz, txz)に対応しました
- PET(Puppy's Extra Treats)パッケージに対応しました
- イメージファイル(ext2, ext3, ext4)に対応しました
- 名前をdeb2sfs.shからpackage2sfsに変更しました
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
これって例えば、20個くらいのdebファイルをフォルダに入れてそのフォルダを指定してsfsを作成することは可能でしょうか?
例 ./deb2sfs aaaa.sfs /mnt/sdc1
例 ./deb2sfs aaaa.sfs /mnt/sdc1
-
- 記事: 2092
- 登録日時: 15/10/25(日) 14:00
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
3個の deb ファイルで試したところ、sfs が作成されました。20個は試したことがありませんが、可能だと思います。生成された sfs がちゃんと機能するかどうかは、実際に動かしてみないと分かりません。
追記
フォルダを指定するとうまくいきません。フォルダに移動して実行する必要があります。例えば、/mnt/sda5/work に deb ファイルがある場合
# cd /mnt/sda5/work
# /root/my-applications/package2sfs example.sfs *.deb
(この場合 package2sfs は /root/my-applications にあります。)
ThinkPad X121e (Precise 571 / Tahr 605 / Tahr64 606 / Xenial 7.5 / Bionic32)
CPU AMD C-50 1.0GHz, RAM 4GB
ThinkPad L440 (Xenial 7.5 / Bionic64 / Fossa64)
CPU intel Celeron 2950M 2.0GHz, RAM 4GB
CPU AMD C-50 1.0GHz, RAM 4GB
ThinkPad L440 (Xenial 7.5 / Bionic64 / Fossa64)
CPU intel Celeron 2950M 2.0GHz, RAM 4GB
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
返信ありがとうございます!とりあえず実際に試してみようと思います。分かりやすく教えてくださりありがとうございました!
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
最近また Puppy Linux の使用を再開したのですが、過去に作成したスクリプトがあまりに拙かったのでリファクタリングを行いました。
リファクタリングなので、目新しい機能になどは特にありませんが、一部のオプション名の変更などがあります。主な詳しい変更点は以下です。
Precise-571JP で動作することを確認しております。よろしければ利用してみてくださいね。
2022年10月29日追記
ちまちまとバグ取りや高速化を行っています。バージョンも 2.0.2 まで上がりました。
コード: 全て選択
#!/usr/bin/env sh
### Script: package2sfs
##
## パッケージを SquashFS に変換する。
##
## Metadata:
##
## id - 38559dfa-cda3-4325-a702-d29aabbb6f85
## author - <ssnys at https://sakurapup.com/forum1/memberlist.php?mode=viewprofile&u=4849>
## version - 2.0.2
## date - 2022-10-28
## since - 2018-06-22
## copyright - Copyright (C) 2018-2022 ssnys. Some rights reserved.
## license - <CC-BY at https://creativecommons.org/licenses/by/4.0/>
##
## See Also:
##
## * <Project homepage at https://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
##
## Help Output:
##
## ------ Text ------
## Usage:
## package2sfs [OPTION]... DEST [PACKAGE]...
##
## Options:
## -c, --{no-}control[=PACKAGE_NUMBER_LIST]
## build package control file
## -d, --{no-}directory do not make SquashFS but directory
## -o, --option NAME[=VALUE]
## option of mksquashfs command
## --no-option reset -o, --option
## -v, --{no-}verbose enable verbose output
## -h, --help display this help and exit
## -V, --version output version information and exit
##
## Exit Status:
## 0 - successful termination
## 64 - command line usage error
## 65 - data format error
## 66 - cannot open input
## 67 - addressee unknown
## 68 - host name unknown
## 69 - service unavailable
## 70 - internal software error
## 71 - system error (e.g., can't fork)
## 72 - critical OS file missing
## 73 - can't create (user) output file
## 74 - input/output error
## 75 - temp failure; user is invited to retry
## 76 - remote error in protocol
## 77 - permission denied
## 78 - configuration error
## 129 - received SIGHUP
## 130 - received SIGINT
## 131 - received SIGQUIT
## 143 - received SIGTERM
##
## Examples:
## package2sfs output.sfs *.deb
## package2sfs -cv output.sfs *.pet
## package2sfs -c2,3 output.sfs package1.tgz package2.tgz package3.tgz
## package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
## package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
## ------------------
readonly 'NAME=package2sfs'
readonly 'VERSION=2.0.2'
readonly 'UPDATE=2022-10-28'
set -efu
umask '0022'
LC_ALL='C'
IFS=$(printf ' \t\n_'); IFS="${IFS%_}"
PATH="${PATH-}${PATH:+:}$(command -p getconf 'PATH')"
UNIX_STD='2003' # HP-UX POSIX mode
XPG_SUS_ENV='ON' # AIX POSIX mode
XPG_UNIX98='OFF' # AIX UNIX 03 mode
POSIXLY_CORRECT='1' # GNU Coreutils POSIX mode
COMMAND_MODE='unix2003' # macOS UNIX 03 mode
export 'IFS' 'LC_ALL' 'PATH' 'UNIX_STD' 'XPG_SUS_ENV' 'XPG_UNIX98' 'POSIXLY_CORRECT' 'COMMAND_MODE'
readonly 'EX_OK=0' # successful termination
readonly 'EX__BASE=64' # base value for error messages
readonly 'EX_USAGE=64' # command line usage error
readonly 'EX_DATAERR=65' # data format error
readonly 'EX_NOINPUT=66' # cannot open input
readonly 'EX_NOUSER=67' # addressee unknown
readonly 'EX_NOHOST=68' # host name unknown
readonly 'EX_UNAVAILABLE=69' # service unavailable
readonly 'EX_SOFTWARE=70' # internal software error
readonly 'EX_OSERR=71' # system error (e.g., can't fork)
readonly 'EX_OSFILE=72' # critical OS file missing
readonly 'EX_CANTCREAT=73' # can't create (user) output file
readonly 'EX_IOERR=74' # input/output error
readonly 'EX_TEMPFAIL=75' # temp failure; user is invited to retry
readonly 'EX_PROTOCOL=76' # remote error in protocol
readonly 'EX_NOPERM=77' # permission denied
readonly 'EX_CONFIG=78' # configuration error
readonly 'EX__MAX=78' # maximum listed value
trap 'case "${?}" in 0) end_call;; *) end_call "${EX_SOFTWARE}";; esac' 0 # EXIT
trap 'end_call 129' 1 # SIGHUP
trap 'end_call 130' 2 # SIGINT
trap 'end_call 131' 3 # SIGQUIT
trap 'end_call 143' 15 # SIGTERM
### Function: end_call
##
## 一時ディレクトリを削除しスクリプトを終了する。
##
## Parameters:
##
## $1 - 終了ステータス。
##
## Returns:
##
## $1 の終了ステータス。
end_call() {
trap '' 0 # EXIT
rm -fr -- ${tmpDir:+"${tmpDir}"}
exit "${1:-0}"
}
### Function: option_error
##
## エラーメッセージを出力する。
##
## Parameters:
##
## $1 - エラーメッセージ。
##
## Returns:
##
## 終了コード64。
option_error() {
printf '%s: %s\n' "${0##*/}" "${1}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
}
### Function: append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $@ - 追加する要素。
append_array_posix() {
while [ 2 -le "${#}" ]; do
__append_array_posix "${1}" "${2}"
eval "shift 2; set -- '${1}'" '${@+"${@}"}'
done
}
### Function: __append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 追加する要素。
__append_array_posix() {
set "${1}" "${2-}" ''
until [ "${2#*\'}" '=' "${2}" ]; do
set -- "${1}" "${2#*\'}" "${3}${2%%\'*}'\"'\"'"
done
eval "${1}=\"\${${1}-}\${${1}:+ }'\${3}\${2}'\""
}
### Function: regex_match
##
## 文字列が正規表現に一致するか検査する。
##
## Parameters:
##
## $1 - 検査する文字列。
## $@ - 正規表現。
##
## Returns:
##
## 0か1の真理値。
regex_match() {
awk -- '
BEGIN {
for(i = 2; i < ARGC; i++) {
if(ARGV[1] !~ ARGV[i]) {
exit 1
}
}
exit
}
' ${@+"${@}"} || return 1
return 0
}
### Function: add_option
##
## オプションを追加する
##
## Parameters:
##
## $1 - Debian パッケージ
## $2 - オプションの名前と値
add_option() {
case "${2}" in
*'='*) append_array_posix "${1}" "-${2%%=*}" "${2#*=}";;
*) append_array_posix "${1}" "-${2}";;
esac
}
### Function: deb2dir
##
## Debian パッケージを展開する
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 展開先のディレクトリ
deb2dir() (
package="${1}"
dir="${2}"
# Debian パッケージからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf '# Extract files in %s #\n' "${package}";;
esac
dpkg-deb --extract ${prog_v+-v} -- "${package}" "${dir}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}.deb' -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# Debian パッケージからコントロールファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf "# Extract control files in '%s' #\\n" "${package}";;
esac
dpkg-deb --control ${prog_v+-v} -- "${package}" "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}${controlDir}/preinst" ] || [ -x "${dir}${controlDir}/postinst" ] || [ -x "${dir}${controlDir}/prerm" ] || [ -x "${dir}${controlDir}/postrm" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/preinst' ]; then
'${controlDir}/preinst' 'install'
fi
if [ -x '${controlDir}/postinst' ]; then
'${controlDir}/postinst' 'configure' '$(dpkg-deb -W --showformat='${Version}' -- "${package}")'
fi
;;
'stop')
if [ -x '${controlDir}/prerm' ]; then
'${controlDir}/prerm' 'remove'
fi
if [ -x '${controlDir}/postrm' ]; then
'${controlDir}/postrm' 'remove'
fi
;;
__EOF__
fi
esac
)
### Function: pet2dir
##
## Puppy's Extra Treats パッケージを展開する
##
## Parameters:
##
## $1 - PET パッケージ
## $2 - 展開先のディレクトリ
pet2dir() (
package="${1}"
dir="${2}"
basename=$(basename -- "${package}" '.pet')
tmpPet=$(mktemp -d)
cp -f ${prog_v+-v} -- "${package}" "${tmpPet}/package.pet"
if pet2tgz "${tmpPet}/package.pet"; then :; else
rm -fr -- "${tmpPet}"
printf "%s: '%s' is broken.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
return 1
fi
# Puppy's Extra Treats パッケージからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf "# Extract files in '%s' #\\n" "${package}";;
esac
tar -xz -C "${tmpPet}" -f "${tmpPet}/package.tar.gz" ${prog_v+-v}
if [ -d "${tmpPet}/${basename}" ]; then
find -- "${tmpPet}/${basename}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}" ';'
fi
rm -fr ${prog_v+-v} -- "${tmpPet}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}/pinstall.sh" ] || [ -x "${dir}/puninstall.sh" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/pinstall.sh' ]; then
'${controlDir}/pinstall.sh'
fi
;;
'stop')
if [ -x '${controlDir}/puninstall.sh' ]; then
'${controlDir}/puninstall.sh'
fi
;;
__EOF__
fi
for controlFile in 'pinstall.sh' 'puninstall.sh' 'pet.specs'; do
if [ -f "${dir}/${controlFile}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' files #\\n" "${dir}/${controlFile}";;
esac
cp -f ${prog_v+-v} -- "${dir}/${controlFile}" "${dir}${controlDir}"
fi
done
esac
rm -fr ${prog_v+-v} -- "${dir}/pinstall.sh" "${dir}/puinstall.sh" "${dir}/pet.specs"
)
### Function: pkg2dir
##
## Slackware パッケージを展開する
##
## Parameters:
##
## $1 - Slackware パッケージ
## $2 - 展開先のディレクトリ
pkg2dir() (
package="${1}"
dir="${2}"
# 圧縮ファイルからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf '# Extract files in %s #\n' "${package}";;
esac
case "${package}" in
*'.tgz') tar -xz -C "${dir}" -f "${package}" ${prog_v+-v};;
*'.txz') tar -xJ -C "${dir}" -f "${package}" ${prog_v+-v};;
esac
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -f "${dir}/install/doinst.sh" ]; then
chmod ${prog_v+-v} -- '755' "${dir}/install/doinst.sh"
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/doinst.sh' ]; then
'${controlDir}/doinst.sh'
fi
;;
'stop') ;;
__EOF__
fi
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' directory #\\n" "${dir}/install";;
esac
if [ -d "${dir}/install" ]; then
find -- "${dir}/install/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}${controlDir}" ';'
fi
esac
rm -fr ${prog_v+-v} -- "${dir}/install"
)
### Function: startup_script
##
## サービス起動スクリプトを作成する
##
## Parameters:
##
## $1 - 作成先のファイルパス
startup_script() (
startup="${1}"
basename=$(basename -- "${startup}" '.sh')
basedir=$(dirname -- "${startup}")
shift
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${basedir}";;
esac
mkdir -p ${prog_v+-v} -- "${basedir}"
# サービス起動スクリプトを作成
case "${verboseFlag}" in
[!0]*) printf "# Create service startup script in '%s' #\\n" "${startup}";;
esac
# サービス起動スクリプトを作成
cat >"${startup}" <<__EOF__
#!/bin/sh
## Startup ${basename} maintainer scripts
#
# @date $(date -u -- '+%Y-%m-%d %H:%M:%S UTC')
# @note Automatically generated by ${NAME} version ${VERSION} (update ${UPDATE})
set -efu
cd -- '/'
case "\${1}" in
$(cat)
'restart')
shift
"\${0}" 'stop' \${@+"\${@}"}
"\${0}" 'start' \${@+"\${@}"}
;;
*)
printf 'Usage: %s {start|stop|restart}\\n' "\${0}" >&2
# EX_USAGE (/usr/include/sysexits.h)
exit '${EX_USAGE}'
;;
esac
__EOF__
# パーミッションを変更し実行が可能に
case "${verboseFlag}" in
[!0]*) printf "# Chenge mod '%s' #\\n" "${startup}";;
esac
chmod ${prog_v+-v} -- '755' "${startup}"
)
# @getoptions
parser_definition() {
setup REST abbr:true error:option_error plus:true no:0 help:usage \
-- 'Usage:' " ${2##*/} [OPTION]... DEST [PACKAGE]..." \
'' 'Options:'
option control -c --{no-}control init:@no on:'*' no: validate:'regex_match "${OPTARG}" "^\\*?$|^[1-9][0-9]*(,[1-9][0-9]*)*$"' var:'PACKAGE_NUMBER_LIST' -- 'build package control file'
flag dirFlag -d --{no-}directory init:@no -- 'do not make SquashFS but directory'
param :'add_option "options" "${OPTARG}"' -o --option validate:'regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"' var:'NAME[=VALUE]' -- 'option of mksquashfs command'
flag options --no-option init:@no on: no: -- 'reset -o, --option'
flag verboseFlag -v --{no-}verbose init:@no counter:1 -- 'enable verbose output'
disp :usage -h --help -- 'display this help and exit'
disp :'echo "${NAME} ${VERSION}"' -V --version -- 'output version information and exit'
msg -- '' 'Exit Status:' \
' 0 - successful termination' \
' 64 - command line usage error' \
' 65 - data format error' \
' 66 - cannot open input' \
' 67 - addressee unknown' \
' 68 - host name unknown' \
' 69 - service unavailable' \
' 70 - internal software error' \
" 71 - system error (e.g., can't fork)" \
' 72 - critical OS file missing' \
" 73 - can't create (user) output file" \
' 74 - input/output error' \
' 75 - temp failure; user is invited to retry' \
' 76 - remote error in protocol' \
' 77 - permission denied' \
' 78 - configuration error' \
' 129 - received SIGHUP' \
' 130 - received SIGINT' \
' 131 - received SIGQUIT' \
' 143 - received SIGTERM'
msg -- '' 'Examples:' \
" ${2##*/} output.sfs *.deb" \
" ${2##*/} -cv output.sfs *.pet" \
" ${2##*/} -c2,3 output.sfs package1.tgz package2.tgz package3.tgz" \
" ${2##*/} -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir" \
" ${2##*/} output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'"
}
# @end
# @gengetoptions parser -i parser_definition parse "${1}"
# Generated by getoptions (BEGIN)
# URL: https://github.com/ko1nksm/getoptions (v3.3.0)
control=''
dirFlag='0'
options=''
verboseFlag='0'
REST=''
parse() {
OPTIND=$(($#+1))
while OPTARG= && [ $# -gt 0 ]; do
set -- "${1%%\=*}" "${1#*\=}" "$@"
while [ ${#1} -gt 2 ]; do
case $1 in (*[!a-zA-Z0-9_-]*) break; esac
case '--control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --control"
esac
case '--no-control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-control"
esac
case '--directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --directory"
esac
case '--no-directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-directory"
esac
case '--option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --option"
esac
case '--no-option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-option"
esac
case '--verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --verbose"
esac
case '--no-verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-verbose"
esac
case '--help' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --help"
esac
case '--version' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --version"
esac
break
done
case ${OPTARG# } in
*\ *)
eval "set -- $OPTARG $1 $OPTARG"
OPTIND=$((($#+1)/2)) OPTARG=$1; shift
while [ $# -gt "$OPTIND" ]; do OPTARG="$OPTARG, $1"; shift; done
set "Ambiguous option: $1 (could be $OPTARG)" ambiguous "$@"
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1 ;;
?*)
[ "$2" = "$3" ] || OPTARG="$OPTARG=$2"
shift 3; eval 'set -- "${OPTARG# }"' ${1+'"$@"'}; OPTARG= ;;
*) shift 2
esac
case $1 in
--?*=*) OPTARG=$1; shift
eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
;;
--no-*|--without-*) unset OPTARG ;;
-[co]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" "${OPTARG#??}"' ${1+'"$@"'}
;;
-[dvhV]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
OPTARG= ;;
+*) unset OPTARG ;;
esac
case $1 in
'-c'|'--control'|'--no-control')
set -- "$1" "$@"
[ ${OPTARG+x} ] && {
case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
[ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='*'
} || OPTARG=''
regex_match "${OPTARG}" "^\*?$|^[1-9][0-9]*(,[1-9][0-9]*)*$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^\*?$|^[1-9][0-9]*(,[1-9][0-9]*)*$"; break; }
control="$OPTARG"
shift ;;
'-d'|'--directory'|'--no-directory')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG='0'
dirFlag="$OPTARG"
;;
'-o'|'--option')
[ $# -le 1 ] && set "required" "$1" && break
OPTARG=$2
regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"; break; }
add_option "options" "${OPTARG}"
shift ;;
'--no-option')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='' || OPTARG=''
options="$OPTARG"
;;
'-v'|'--verbose'|'--no-verbose')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG=1 || OPTARG=-1
verboseFlag="$((${verboseFlag:-0}+$OPTARG))"
;;
'-h'|'--help')
usage
exit 0 ;;
'-V'|'--version')
echo "${NAME} ${VERSION}"
exit 0 ;;
--)
shift
while [ $# -gt 0 ]; do
REST="${REST} \"\${$(($OPTIND-$#))}\""
shift
done
break ;;
[-+]?*) set "unknown" "$1"; break ;;
*)
REST="${REST} \"\${$(($OPTIND-$#))}\""
esac
shift
done
[ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
case $1 in
unknown) set "Unrecognized option: $2" "$@" ;;
noarg) set "Does not allow an argument: $2" "$@" ;;
required) set "Requires an argument: $2" "$@" ;;
pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
notcmd) set "Not a command: $2" "$@" ;;
*) set "Validation error ($1): $2" "$@"
esac
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1
}
usage() {
cat<<'GETOPTIONSHERE'
Usage:
package2sfs [OPTION]... DEST [PACKAGE]...
Options:
-c, --{no-}control[=PACKAGE_NUMBER_LIST]
build package control file
-d, --{no-}directory do not make SquashFS but directory
-o, --option NAME[=VALUE]
option of mksquashfs command
--no-option reset -o, --option
-v, --{no-}verbose enable verbose output
-h, --help display this help and exit
-V, --version output version information and exit
Exit Status:
0 - successful termination
64 - command line usage error
65 - data format error
66 - cannot open input
67 - addressee unknown
68 - host name unknown
69 - service unavailable
70 - internal software error
71 - system error (e.g., can't fork)
72 - critical OS file missing
73 - can't create (user) output file
74 - input/output error
75 - temp failure; user is invited to retry
76 - remote error in protocol
77 - permission denied
78 - configuration error
129 - received SIGHUP
130 - received SIGINT
131 - received SIGQUIT
143 - received SIGTERM
Examples:
package2sfs output.sfs *.deb
package2sfs -cv output.sfs *.pet
package2sfs -c2,3 output.sfs package1.tgz package2.tgz package3.tgz
package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
GETOPTIONSHERE
}
# Generated by getoptions (END)
# @end
parse ${@+"${@}"}
eval "set -- ${REST}"
# コマンドライン引数が不足している
case "${#}" in '0')
printf '%s: Requires an argument: DEST\n' "${0##*/}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
;;
esac
# コマンド毎に詳細表示を行うか
if [ '2' -le "${verboseFlag}" ]; then
prog_v='1'
fi
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
case "${verboseFlag}" in
[!0]*) printf '# Make temporary directory and temporary file #\n';;
esac
tmpDir=$(mktemp -d)
tmpContent="${tmpDir}/content"
tmpDownload="${tmpDir}/download"
tmpPackage="${tmpDir}/package"
mkdir -p ${prog_v+-v} -- "${tmpContent}" "${tmpDownload}" "${tmpPackage}"
# 各パッケージを処理
for package in ${@+"${@}"}; do
index=$((${index:-0} + 1))
# パッケージの固有の設定ファイルを展開するか
case "${control}" in
'*' | "${index}" | *",${index}" | "${index},"* | *",${index},"*) controlFlag='1';;
*) controlFlag='0';;
esac
# URL ならばタウンロード
case "${package}" in
'http://'*/* | 'https://'*/* | 'ftp://'*/*)
filename=$(basename -- "${package}")
case "${verboseFlag}" in
[!0]*) printf "# Download '%s' #\\n" "${package}";;
esac
if command -v 'wget' >'/dev/null'; then
wget --no-verbose --output-document "${tmpDownload}/${filename}" ${prog_v+-v} -- "${package}"
elif command -v 'curl' >'/dev/null'; then
curl --compressed --fail --location --output "${tmpDownload}/${filename}" --silent --show-error ${prog_v+-v} -- "${package}"
else
printf "'wget' or 'curl' is required.\\n" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_UNAVAILABLE}"
fi
package="${tmpDownload}/${filename}"
;;
esac
# 読み込みの許可がない
if [ '!' -r "${package}" ]; then
printf "%s: No permission to read '%s'.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_NOINPUT}"
# ディレクトリ
elif [ -d "${package}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Copy files in '%s' #\\n" "${package}";;
esac
find -- "${package}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
continue
elif [ '!' -f "${package}" ]; then
printf "%s: '%s' is not a regular file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
fi
# パッケージファイルの種類によって処理を分岐
case "${package}" in
# Debian パッケージ
*[!./]'.deb') deb2dir "${package}" "${tmpContent}";;
# Puppy's Extra Treats
*[!./]'.pet') pet2dir "${package}" "${tmpPackage}";;
# Slackware GZIP or Slackware XZ
*[!./]'.tgz' | '.txz') pkg2dir "${package}" "${tmpPackage}";;
# イメージファイル (ext2, ext3, ext4) と SquashFS ファイル
*[!./].[234]fs | *[!./]'.sfs')
case "${verboseFlag}" in
[!0]*) printf "# Mount '%s' #\\n" "${package}";;
esac
case "${package}" in
*[!./].[234]fs) mount -o 'loop' -r -t 'ext2,ext3,ext4' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
*[!./]'.sfs') mount -r -t 'squashfs' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
esac
case "${verboseFlag}" in
[!0]*) printf "# Copy the files in '%s' #\\n" "${package}";;
esac
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
case "${verboseFlag}" in
[!0]*) printf "# Unmount '%s' #\\n" "${package}";;
esac
umount -d ${prog_v+-v} -- "${tmpPackage}"
;;
# 互換性のないファイル
*)
printf "%s: '%s' is not a compatible file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
;;
esac
# 解凍したファイルをメインのディレクトリに移動
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec rm -fr ${prog_v+-v} -- '{}' '+'
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
if [ -d "${tmpContent}${path}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' #\\n" "${path}";;
esac
find -- "${tmpContent}${path}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}${path}/.." ';'
rm -fr ${prog_v+-v} -- "${tmpContent}${path}"
fi
done
# ${dirFlag} による処理の分岐
case "${dirFlag}" in
'1')
# 一時ディレクトリの内容を ${dest} にコピー
case "${verboseFlag}" in
[!0]*) printf "# Copy temporary directory to '%s' #\\n" "${dest}";;
esac
mkdir -p ${prog_v+-v} -- "${dest}"
find -- "${tmpContent}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dest}" ';'
;;
*)
# SquashFS ファイルを作成
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' #\\n" "${dest}";;
esac
eval 'mksquashfs "${tmpContent}" "${dest}"' "${options}"
;;
esac
- -c, --control で任意のパッケージのみコントロールファイルを展開することが可能になりました。例えば -c2,3 --control=2,3 で2個目と3個めパッケージのみコントロールファイルを展開します。
- -n, --no-sfs は -d, --directory に置き換わりました。
- -v で冗長な表示、-v -v でさらに冗長な表示を行うように変更されました。
- ファイルの識別を内容ではなく、拡張子によって行うように変更されました。
- wget が存在しない場合、curl を使用するようになりました。
- その他エラーメッセージなどが改善されました。
- ディレクトリ
- Debian パッケージ (*.deb)
- PET パッケージ (*.pet)
- Slackware パッケージ (*.tgz, *.txz)
- SquashFS(SFS) ファイル (*.sfs)
- ext2, ext3, ext4 のイメージファイル (*.2fs, *.3fs, *.4fs)
コード: 全て選択
./package2sfs --help
2022年10月29日追記
ちまちまとバグ取りや高速化を行っています。バージョンも 2.0.2 まで上がりました。
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
ほんの少しだけ機能を追加しました。バージョンは2.1.0になりました。
コード: 全て選択
#!/usr/bin/env sh
### Script: package2sfs
##
## パッケージを SquashFS に変換する。
##
## Metadata:
##
## id - 38559dfa-cda3-4325-a702-d29aabbb6f85
## author - <ssnys at https://sakurapup.com/forum1/memberlist.php?mode=viewprofile&u=4849>
## version - 2.1.0
## date - 2022-10-31
## since - 2018-06-22
## copyright - Copyright (C) 2018-2022 ssnys. Some rights reserved.
## license - <CC-BY at https://creativecommons.org/licenses/by/4.0/>
##
## See Also:
##
## * <Project homepage at https://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
##
## Help Output:
##
## ------ Text ------
## Usage:
## package2sfs [OPTION]... DEST [PACKAGE]...
##
## Options:
## -c, --{no-}control[=PACKAGE_NUMBER_LIST]
## build package control file
## -d, --{no-}directory do not make SquashFS but directory
## -o, --option NAME[=VALUE]
## option of mksquashfs command
## --no-option reset -o, --option
## -v, --{no-}verbose enable verbose output
## -h, --help display this help and exit
## -V, --version output version information and exit
##
## Exit Status:
## 0 - successful termination
## 64 - command line usage error
## 65 - data format error
## 66 - cannot open input
## 67 - addressee unknown
## 68 - host name unknown
## 69 - service unavailable
## 70 - internal software error
## 71 - system error (e.g., can't fork)
## 72 - critical OS file missing
## 73 - can't create (user) output file
## 74 - input/output error
## 75 - temp failure; user is invited to retry
## 76 - remote error in protocol
## 77 - permission denied
## 78 - configuration error
## 129 - received SIGHUP
## 130 - received SIGINT
## 131 - received SIGQUIT
## 143 - received SIGTERM
##
## Examples:
## package2sfs output.sfs *.deb
## package2sfs -cv output.sfs *.pet
## package2sfs -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz
## package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
## package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
## ------------------
readonly 'NAME=package2sfs'
readonly 'VERSION=2.1.0'
readonly 'UPDATE=2022-10-31'
set -efu
umask '0022'
LC_ALL='C'
IFS=$(printf ' \t\n_'); IFS="${IFS%_}"
PATH="${PATH-}${PATH:+:}$(command -p getconf 'PATH')"
UNIX_STD='2003' # HP-UX POSIX mode
XPG_SUS_ENV='ON' # AIX POSIX mode
XPG_UNIX98='OFF' # AIX UNIX 03 mode
POSIXLY_CORRECT='1' # GNU Coreutils POSIX mode
COMMAND_MODE='unix2003' # macOS UNIX 03 mode
export 'IFS' 'LC_ALL' 'PATH' 'UNIX_STD' 'XPG_SUS_ENV' 'XPG_UNIX98' 'POSIXLY_CORRECT' 'COMMAND_MODE'
readonly 'EX_OK=0' # successful termination
readonly 'EX__BASE=64' # base value for error messages
readonly 'EX_USAGE=64' # command line usage error
readonly 'EX_DATAERR=65' # data format error
readonly 'EX_NOINPUT=66' # cannot open input
readonly 'EX_NOUSER=67' # addressee unknown
readonly 'EX_NOHOST=68' # host name unknown
readonly 'EX_UNAVAILABLE=69' # service unavailable
readonly 'EX_SOFTWARE=70' # internal software error
readonly 'EX_OSERR=71' # system error (e.g., can't fork)
readonly 'EX_OSFILE=72' # critical OS file missing
readonly 'EX_CANTCREAT=73' # can't create (user) output file
readonly 'EX_IOERR=74' # input/output error
readonly 'EX_TEMPFAIL=75' # temp failure; user is invited to retry
readonly 'EX_PROTOCOL=76' # remote error in protocol
readonly 'EX_NOPERM=77' # permission denied
readonly 'EX_CONFIG=78' # configuration error
readonly 'EX__MAX=78' # maximum listed value
trap 'case "${?}" in 0) end_call;; *) end_call "${EX_SOFTWARE}";; esac' 0 # EXIT
trap 'end_call 129' 1 # SIGHUP
trap 'end_call 130' 2 # SIGINT
trap 'end_call 131' 3 # SIGQUIT
trap 'end_call 143' 15 # SIGTERM
### Function: end_call
##
## 一時ディレクトリを削除しスクリプトを終了する。
##
## Parameters:
##
## $1 - 終了ステータス。
##
## Returns:
##
## $1 の終了ステータス。
end_call() {
trap '' 0 # EXIT
rm -fr -- ${tmpDir:+"${tmpDir}"}
exit "${1:-0}"
}
### Function: option_error
##
## エラーメッセージを出力する。
##
## Parameters:
##
## $1 - エラーメッセージ。
##
## Returns:
##
## 終了コード64。
option_error() {
printf '%s: %s\n' "${0##*/}" "${1}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
}
### Function: append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $@ - 追加する要素。
append_array_posix() {
while [ 2 -le "${#}" ]; do
__append_array_posix "${1}" "${2}"
eval "shift 2; set -- '${1}'" '${@+"${@}"}'
done
}
### Function: __append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 追加する要素。
__append_array_posix() {
set "${1}" "${2-}" ''
until [ "${2#*\'}" '=' "${2}" ]; do
set -- "${1}" "${2#*\'}" "${3}${2%%\'*}'\"'\"'"
done
eval "${1}=\"\${${1}-}\${${1}:+ }'\${3}\${2}'\""
}
### Function: regex_match
##
## 文字列が正規表現に一致するか検査する。
##
## Parameters:
##
## $1 - 検査する文字列。
## $@ - 正規表現。
##
## Returns:
##
## 0か1の真理値。
regex_match() {
awk -- '
BEGIN {
for(i = 2; i < ARGC; i++) {
if(ARGV[1] !~ ARGV[i]) {
exit 1
}
}
exit
}
' ${@+"${@}"} || return 1
return 0
}
### Function: add_option
##
## オプションを追加する
##
## Parameters:
##
## $1 - Debian パッケージ
## $2 - オプションの名前と値
add_option() {
case "${2}" in
*'='*) append_array_posix "${1}" "-${2%%=*}" "${2#*=}";;
*) append_array_posix "${1}" "-${2}";;
esac
}
### Function: deb2dir
##
## Debian パッケージを展開する
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 展開先のディレクトリ
deb2dir() (
package="${1}"
dir="${2}"
# Debian パッケージからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf '# Extract files in %s #\n' "${package}";;
esac
dpkg-deb --extract ${prog_v+-v} -- "${package}" "${dir}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}.deb' -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# Debian パッケージからコントロールファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf "# Extract control files in '%s' #\\n" "${package}";;
esac
dpkg-deb --control ${prog_v+-v} -- "${package}" "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}${controlDir}/preinst" ] || [ -x "${dir}${controlDir}/postinst" ] || [ -x "${dir}${controlDir}/prerm" ] || [ -x "${dir}${controlDir}/postrm" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/preinst' ]; then
'${controlDir}/preinst' 'install'
fi
if [ -x '${controlDir}/postinst' ]; then
'${controlDir}/postinst' 'configure' '$(dpkg-deb -W --showformat='${Version}' -- "${package}")'
fi
;;
'stop')
if [ -x '${controlDir}/prerm' ]; then
'${controlDir}/prerm' 'remove'
fi
if [ -x '${controlDir}/postrm' ]; then
'${controlDir}/postrm' 'remove'
fi
;;
__EOF__
fi
esac
)
### Function: pet2dir
##
## Puppy's Extra Treats パッケージを展開する
##
## Parameters:
##
## $1 - PET パッケージ
## $2 - 展開先のディレクトリ
pet2dir() (
package="${1}"
dir="${2}"
basename=$(basename -- "${package}" '.pet')
tmpPet=$(mktemp -d)
cp -f ${prog_v+-v} -- "${package}" "${tmpPet}/package.pet"
if pet2tgz "${tmpPet}/package.pet"; then :; else
rm -fr -- "${tmpPet}"
printf "%s: '%s' is broken.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
return 1
fi
# Puppy's Extra Treats パッケージからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf "# Extract files in '%s' #\\n" "${package}";;
esac
tar -xz -C "${tmpPet}" -f "${tmpPet}/package.tar.gz" ${prog_v+-v}
if [ -d "${tmpPet}/${basename}" ]; then
find -- "${tmpPet}/${basename}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}" ';'
fi
rm -fr ${prog_v+-v} -- "${tmpPet}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}/pinstall.sh" ] || [ -x "${dir}/puninstall.sh" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/pinstall.sh' ]; then
'${controlDir}/pinstall.sh'
fi
;;
'stop')
if [ -x '${controlDir}/puninstall.sh' ]; then
'${controlDir}/puninstall.sh'
fi
;;
__EOF__
fi
for controlFile in 'pinstall.sh' 'puninstall.sh' 'pet.specs'; do
if [ -f "${dir}/${controlFile}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' files #\\n" "${dir}/${controlFile}";;
esac
cp -f ${prog_v+-v} -- "${dir}/${controlFile}" "${dir}${controlDir}"
fi
done
esac
rm -fr ${prog_v+-v} -- "${dir}/pinstall.sh" "${dir}/puinstall.sh" "${dir}/pet.specs"
)
### Function: pkg2dir
##
## Slackware パッケージを展開する
##
## Parameters:
##
## $1 - Slackware パッケージ
## $2 - 展開先のディレクトリ
pkg2dir() (
package="${1}"
dir="${2}"
# 圧縮ファイルからファイルを取り出す
case "${verboseFlag}" in
[!0]*) printf '# Extract files in %s #\n' "${package}";;
esac
case "${package}" in
*'.tgz') tar -xz -C "${dir}" -f "${package}" ${prog_v+-v};;
*'.txz') tar -xJ -C "${dir}" -f "${package}" ${prog_v+-v};;
esac
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${dir}${controlDir}";;
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -f "${dir}/install/doinst.sh" ]; then
chmod ${prog_v+-v} -- '755' "${dir}/install/doinst.sh"
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/doinst.sh' ]; then
'${controlDir}/doinst.sh'
fi
;;
'stop') ;;
__EOF__
fi
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' directory #\\n" "${dir}/install";;
esac
if [ -d "${dir}/install" ]; then
find -- "${dir}/install/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}${controlDir}" ';'
fi
esac
rm -fr ${prog_v+-v} -- "${dir}/install"
)
### Function: startup_script
##
## サービス起動スクリプトを作成する
##
## Parameters:
##
## $1 - 作成先のファイルパス
startup_script() (
startup="${1}"
basename=$(basename -- "${startup}" '.sh')
basedir=$(dirname -- "${startup}")
shift
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' directory #\\n" "${basedir}";;
esac
mkdir -p ${prog_v+-v} -- "${basedir}"
# サービス起動スクリプトを作成
case "${verboseFlag}" in
[!0]*) printf "# Create service startup script in '%s' #\\n" "${startup}";;
esac
# サービス起動スクリプトを作成
cat >"${startup}" <<__EOF__
#!/bin/sh
## Startup ${basename} maintainer scripts
#
# @date $(date -u -- '+%Y-%m-%d %H:%M:%S UTC')
# @note Automatically generated by ${NAME} version ${VERSION} (update ${UPDATE})
set -efu
cd -- '/'
case "\${1}" in
$(cat)
'restart')
shift
"\${0}" 'stop' \${@+"\${@}"}
"\${0}" 'start' \${@+"\${@}"}
;;
*)
printf 'Usage: %s {start|stop|restart}\\n' "\${0}" >&2
# EX_USAGE (/usr/include/sysexits.h)
exit '${EX_USAGE}'
;;
esac
__EOF__
# パーミッションを変更し実行が可能に
case "${verboseFlag}" in
[!0]*) printf "# Chenge mod '%s' #\\n" "${startup}";;
esac
chmod ${prog_v+-v} -- '755' "${startup}"
)
# @getoptions
parser_definition() {
setup REST abbr:true error:option_error plus:true no:0 help:usage \
-- 'Usage:' " ${2##*/} [OPTION]... DEST [PACKAGE]..." \
'' 'Options:'
option control -c --{no-}control init:@no on:'1-' no: validate:'regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$"' var:'PACKAGE_NUMBER_LIST' -- 'build package control file'
flag dirFlag -d --{no-}directory init:@no -- 'do not make SquashFS but directory'
param :'add_option "options" "${OPTARG}"' -o --option validate:'regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"' var:'NAME[=VALUE]' -- 'option of mksquashfs command'
flag options --no-option init:@no on: no: -- 'reset -o, --option'
flag verboseFlag -v --{no-}verbose init:@no counter:1 -- 'enable verbose output'
disp :usage -h --help -- 'display this help and exit'
disp :'echo "${NAME} ${VERSION}"' -V --version -- 'output version information and exit'
msg -- '' 'Exit Status:' \
' 0 - successful termination' \
' 64 - command line usage error' \
' 65 - data format error' \
' 66 - cannot open input' \
' 67 - addressee unknown' \
' 68 - host name unknown' \
' 69 - service unavailable' \
' 70 - internal software error' \
" 71 - system error (e.g., can't fork)" \
' 72 - critical OS file missing' \
" 73 - can't create (user) output file" \
' 74 - input/output error' \
' 75 - temp failure; user is invited to retry' \
' 76 - remote error in protocol' \
' 77 - permission denied' \
' 78 - configuration error' \
' 129 - received SIGHUP' \
' 130 - received SIGINT' \
' 131 - received SIGQUIT' \
' 143 - received SIGTERM'
msg -- '' 'Examples:' \
" ${2##*/} output.sfs *.deb" \
" ${2##*/} -cv output.sfs *.pet" \
" ${2##*/} -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz" \
" ${2##*/} -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir" \
" ${2##*/} output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'"
}
# @end
# @gengetoptions parser -i parser_definition parse "${1}"
# Generated by getoptions (BEGIN)
# URL: https://github.com/ko1nksm/getoptions (v3.3.0)
control=''
dirFlag='0'
options=''
verboseFlag='0'
REST=''
parse() {
OPTIND=$(($#+1))
while OPTARG= && [ $# -gt 0 ]; do
set -- "${1%%\=*}" "${1#*\=}" "$@"
while [ ${#1} -gt 2 ]; do
case $1 in (*[!a-zA-Z0-9_-]*) break; esac
case '--control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --control"
esac
case '--no-control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-control"
esac
case '--directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --directory"
esac
case '--no-directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-directory"
esac
case '--option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --option"
esac
case '--no-option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-option"
esac
case '--verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --verbose"
esac
case '--no-verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-verbose"
esac
case '--help' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --help"
esac
case '--version' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --version"
esac
break
done
case ${OPTARG# } in
*\ *)
eval "set -- $OPTARG $1 $OPTARG"
OPTIND=$((($#+1)/2)) OPTARG=$1; shift
while [ $# -gt "$OPTIND" ]; do OPTARG="$OPTARG, $1"; shift; done
set "Ambiguous option: $1 (could be $OPTARG)" ambiguous "$@"
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1 ;;
?*)
[ "$2" = "$3" ] || OPTARG="$OPTARG=$2"
shift 3; eval 'set -- "${OPTARG# }"' ${1+'"$@"'}; OPTARG= ;;
*) shift 2
esac
case $1 in
--?*=*) OPTARG=$1; shift
eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
;;
--no-*|--without-*) unset OPTARG ;;
-[co]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" "${OPTARG#??}"' ${1+'"$@"'}
;;
-[dvhV]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
OPTARG= ;;
+*) unset OPTARG ;;
esac
case $1 in
'-c'|'--control'|'--no-control')
set -- "$1" "$@"
[ ${OPTARG+x} ] && {
case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
[ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='1-'
} || OPTARG=''
regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$"; break; }
control="$OPTARG"
shift ;;
'-d'|'--directory'|'--no-directory')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG='0'
dirFlag="$OPTARG"
;;
'-o'|'--option')
[ $# -le 1 ] && set "required" "$1" && break
OPTARG=$2
regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"; break; }
add_option "options" "${OPTARG}"
shift ;;
'--no-option')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='' || OPTARG=''
options="$OPTARG"
;;
'-v'|'--verbose'|'--no-verbose')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG=1 || OPTARG=-1
verboseFlag="$((${verboseFlag:-0}+$OPTARG))"
;;
'-h'|'--help')
usage
exit 0 ;;
'-V'|'--version')
echo "${NAME} ${VERSION}"
exit 0 ;;
--)
shift
while [ $# -gt 0 ]; do
REST="${REST} \"\${$(($OPTIND-$#))}\""
shift
done
break ;;
[-+]?*) set "unknown" "$1"; break ;;
*)
REST="${REST} \"\${$(($OPTIND-$#))}\""
esac
shift
done
[ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
case $1 in
unknown) set "Unrecognized option: $2" "$@" ;;
noarg) set "Does not allow an argument: $2" "$@" ;;
required) set "Requires an argument: $2" "$@" ;;
pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
notcmd) set "Not a command: $2" "$@" ;;
*) set "Validation error ($1): $2" "$@"
esac
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1
}
usage() {
cat<<'GETOPTIONSHERE'
Usage:
package2sfs [OPTION]... DEST [PACKAGE]...
Options:
-c, --{no-}control[=PACKAGE_NUMBER_LIST]
build package control file
-d, --{no-}directory do not make SquashFS but directory
-o, --option NAME[=VALUE]
option of mksquashfs command
--no-option reset -o, --option
-v, --{no-}verbose enable verbose output
-h, --help display this help and exit
-V, --version output version information and exit
Exit Status:
0 - successful termination
64 - command line usage error
65 - data format error
66 - cannot open input
67 - addressee unknown
68 - host name unknown
69 - service unavailable
70 - internal software error
71 - system error (e.g., can't fork)
72 - critical OS file missing
73 - can't create (user) output file
74 - input/output error
75 - temp failure; user is invited to retry
76 - remote error in protocol
77 - permission denied
78 - configuration error
129 - received SIGHUP
130 - received SIGINT
131 - received SIGQUIT
143 - received SIGTERM
Examples:
package2sfs output.sfs *.deb
package2sfs -cv output.sfs *.pet
package2sfs -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz
package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
GETOPTIONSHERE
}
# Generated by getoptions (END)
# @end
parse ${@+"${@}"}
eval "set -- ${REST}"
# コマンドライン引数が不足している
case "${#}" in '0')
printf '%s: Requires an argument: DEST\n' "${0##*/}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
;;
esac
# コマンド毎に詳細表示を行うか
if [ '2' -le "${verboseFlag}" ]; then
prog_v='1'
fi
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
case "${verboseFlag}" in
[!0]*) printf '# Make temporary directory and temporary file #\n';;
esac
awkRangeCheckScript=$(
cat <<-'__EOF__'
BEGIN {
number = ARGV[1]
split(ARGV[2], ranges, ",")
for(i in ranges) {
if(index(ranges[i], "-")) {
split(ranges[i], array, "-")
if(array[1] != "" && array[2] != "" && array[2] < array[1]) {
tmp = array[1]
array[1] = array[2]
array[2] = tmp
}
if((array[1] == "" || array[1] <= number) && (array[2] == "" || number <= array[2])) {
exit
}
} else if(ranges[i] == number) {
exit
}
}
exit 1
}
__EOF__
)
tmpDir=$(mktemp -d)
tmpContent="${tmpDir}/content"
tmpDownload="${tmpDir}/download"
tmpPackage="${tmpDir}/package"
mkdir -p ${prog_v+-v} -- "${tmpContent}" "${tmpDownload}" "${tmpPackage}"
# 各パッケージを処理
for package in ${@+"${@}"}; do
index=$((${index:-0} + 1))
controlFlag='0'
if awk -- "${awkRangeCheckScript}" "${index}" "${control}"; then
controlFlag='1'
fi
# URL ならばタウンロード
case "${package}" in
'http://'*/* | 'https://'*/* | 'ftp://'*/*)
filename=$(basename -- "${package}")
case "${verboseFlag}" in
[!0]*) printf "# Download '%s' #\\n" "${package}";;
esac
if command -v 'wget' >'/dev/null'; then
wget --no-verbose --output-document "${tmpDownload}/${filename}" ${prog_v+-v} -- "${package}"
elif command -v 'curl' >'/dev/null'; then
curl --compressed --fail --location --output "${tmpDownload}/${filename}" --silent --show-error ${prog_v+-v} -- "${package}"
else
printf "'wget' or 'curl' is required.\\n" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_UNAVAILABLE}"
fi
package="${tmpDownload}/${filename}"
;;
esac
# 読み込みの許可がない
if [ '!' -r "${package}" ]; then
printf "%s: No permission to read '%s'.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_NOINPUT}"
# ディレクトリ
elif [ -d "${package}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Copy files in '%s' #\\n" "${package}";;
esac
find -- "${package}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
continue
elif [ '!' -f "${package}" ]; then
printf "%s: '%s' is not a regular file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
fi
# パッケージファイルの種類によって処理を分岐
case "${package}" in
# Debian パッケージ
*[!./]'.deb') deb2dir "${package}" "${tmpContent}";;
# Puppy's Extra Treats
*[!./]'.pet') pet2dir "${package}" "${tmpPackage}";;
# Slackware GZIP or Slackware XZ
*[!./]'.tgz' | '.txz') pkg2dir "${package}" "${tmpPackage}";;
# イメージファイル (ext2, ext3, ext4) と SquashFS ファイル
*[!./].[234]fs | *[!./]'.sfs')
case "${verboseFlag}" in
[!0]*) printf "# Mount '%s' #\\n" "${package}";;
esac
case "${package}" in
*[!./].[234]fs) mount -o 'loop' -r -t 'ext2,ext3,ext4' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
*[!./]'.sfs') mount -r -t 'squashfs' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
esac
case "${verboseFlag}" in
[!0]*) printf "# Copy the files in '%s' #\\n" "${package}";;
esac
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
case "${verboseFlag}" in
[!0]*) printf "# Unmount '%s' #\\n" "${package}";;
esac
umount -d ${prog_v+-v} -- "${tmpPackage}"
;;
# 互換性のないファイル
*)
printf "%s: '%s' is not a compatible file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
;;
esac
# 解凍したファイルをメインのディレクトリに移動
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec rm -fr ${prog_v+-v} -- '{}' '+'
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
if [ -d "${tmpContent}${path}" ]; then
case "${verboseFlag}" in
[!0]*) printf "# Move '%s' #\\n" "${path}";;
esac
find -- "${tmpContent}${path}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}${path}/.." ';'
rm -fr ${prog_v+-v} -- "${tmpContent}${path}"
fi
done
# ${dirFlag} による処理の分岐
case "${dirFlag}" in
'1')
# 一時ディレクトリの内容を ${dest} にコピー
case "${verboseFlag}" in
[!0]*) printf "# Copy temporary directory to '%s' #\\n" "${dest}";;
esac
mkdir -p ${prog_v+-v} -- "${dest}"
find -- "${tmpContent}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dest}" ';'
;;
*)
# SquashFS ファイルを作成
case "${verboseFlag}" in
[!0]*) printf "# Make '%s' #\\n" "${dest}";;
esac
eval 'mksquashfs "${tmpContent}" "${dest}"' "${options}"
;;
esac
- -c, --control オプションで範囲を指定できるようになりました。例えば --control=1,3-5,9- ですと、引数の1個目、3個目から5個目、9個目以降のパッケージにてコントロールファイルが展開されます。
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
Re: deb2sfs.sh - deb(Debianパッケージ)をsfs(SquashFS)に変換するシェルスクリプト
RPM パッケージに対応しました。CentOS などのパッケージが利用できるようになりました。バージョンは2.2.0になりました。
package2sfs は現在、以下の内容から Puppy Linux 用の新たな SFS ファイルを作成できます。
*.txz が処理できないバグを修正しました。バージョンは2.2.1になりました。
2024年01月11日追記
'/lib/i386-linux-gnu', '/usr/bin/i386-linux-gnu', '/usr/lib/i386-linux-gnu' における処理を少し改善しました。これで 'devx_precise_5.7.1.sfs' などを正常に展開できます。バージョンは2.2.2になりました。
コード: 全て選択
#!/usr/bin/env sh
### Script: package2sfs
##
## パッケージを SquashFS に変換する。
##
## Metadata:
##
## id - 38559dfa-cda3-4325-a702-d29aabbb6f85
## author - <ssnys at https://sakurapup.com/forum1/memberlist.php?mode=viewprofile&u=4849>
## version - 2.2.2
## date - 2023-12-26
## since - 2018-06-22
## copyright - Copyright (C) 2018-2022 ssnys. Some rights reserved.
## license - <CC-BY at https://creativecommons.org/licenses/by/4.0/>
##
## See Also:
##
## * <Project homepage at https://sakurapup.com/forum1/viewtopic.php?f=31&t=3372>
##
## Help Output:
##
## ------ Text ------
## Usage:
## package2sfs [OPTION]... DEST [PACKAGE]...
##
## Options:
## -c, --{no-}control[=PACKAGE_NUMBER_LIST]
## build package control file
## -d, --{no-}directory do not make SquashFS but directory
## -o, --option NAME[=VALUE]
## option of mksquashfs command
## --no-option reset -o, --option
## -v, --{no-}verbose enable verbose output
## -h, --help display this help and exit
## -V, --version output version information and exit
##
## Exit Status:
## 0 - successful termination
## 64 - command line usage error
## 65 - data format error
## 66 - cannot open input
## 67 - addressee unknown
## 68 - host name unknown
## 69 - service unavailable
## 70 - internal software error
## 71 - system error (e.g., can't fork)
## 72 - critical OS file missing
## 73 - can't create (user) output file
## 74 - input/output error
## 75 - temp failure; user is invited to retry
## 76 - remote error in protocol
## 77 - permission denied
## 78 - configuration error
## 129 - received SIGHUP
## 130 - received SIGINT
## 131 - received SIGQUIT
## 143 - received SIGTERM
##
## Examples:
## package2sfs output.sfs *.deb
## package2sfs -cv output.sfs *.pet
## package2sfs -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz
## package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
## package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
## ------------------
readonly 'NAME=package2sfs'
readonly 'VERSION=2.2.2'
readonly 'UPDATE=2023-12-26'
set -efu
umask '0022'
readonly "LC_ALL_ORG=${LC_ALL-}"
LC_ALL='C'
IFS=$(printf ' \t\n_'); IFS="${IFS%_}"
PATH="${PATH-}${PATH:+:}$(command -p getconf 'PATH')"
UNIX_STD='2003' # HP-UX POSIX mode
XPG_SUS_ENV='ON' # AIX POSIX mode
XPG_UNIX98='OFF' # AIX UNIX 03 mode
POSIXLY_CORRECT='1' # GNU Coreutils POSIX mode
COMMAND_MODE='unix2003' # macOS UNIX 03 mode
export 'LC_ALL' 'IFS' 'PATH' 'UNIX_STD' 'XPG_SUS_ENV' 'XPG_UNIX98' 'POSIXLY_CORRECT' 'COMMAND_MODE'
readonly 'EX_OK=0' # successful termination
readonly 'EX__BASE=64' # base value for error messages
readonly 'EX_USAGE=64' # command line usage error
readonly 'EX_DATAERR=65' # data format error
readonly 'EX_NOINPUT=66' # cannot open input
readonly 'EX_NOUSER=67' # addressee unknown
readonly 'EX_NOHOST=68' # host name unknown
readonly 'EX_UNAVAILABLE=69' # service unavailable
readonly 'EX_SOFTWARE=70' # internal software error
readonly 'EX_OSERR=71' # system error (e.g., can't fork)
readonly 'EX_OSFILE=72' # critical OS file missing
readonly 'EX_CANTCREAT=73' # can't create (user) output file
readonly 'EX_IOERR=74' # input/output error
readonly 'EX_TEMPFAIL=75' # temp failure; user is invited to retry
readonly 'EX_PROTOCOL=76' # remote error in protocol
readonly 'EX_NOPERM=77' # permission denied
readonly 'EX_CONFIG=78' # configuration error
readonly 'EX__MAX=78' # maximum listed value
trap 'case "${?}" in 0) end_call;; *) end_call "${EX_SOFTWARE}";; esac' 0 # EXIT
trap 'end_call 129' 1 # SIGHUP
trap 'end_call 130' 2 # SIGINT
trap 'end_call 131' 3 # SIGQUIT
trap 'end_call 143' 15 # SIGTERM
alias org_lc='LC_ALL="${LC_ALL_ORG}"'
### Function: end_call
##
## 一時ディレクトリを削除しスクリプトを終了する。
##
## Parameters:
##
## $1 - 終了ステータス。
##
## Returns:
##
## $1 の終了ステータス。
end_call() {
trap '' 0 # EXIT
rm -fr -- ${tmpDir:+"${tmpDir}"}
exit "${1:-0}"
}
### Function: option_error
##
## エラーメッセージを出力する。
##
## Parameters:
##
## $1 - エラーメッセージ。
##
## Returns:
##
## 終了コード64。
option_error() {
printf '%s: %s\n' "${0##*/}" "${1}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
}
### Function: append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $@ - 追加する要素。
append_array_posix() {
while [ 2 -le "${#}" ]; do
__append_array_posix "${1}" "${2}"
eval "shift 2; set -- '${1}'" '${@+"${@}"}'
done
}
### Function: __append_array_posix
##
## 配列風文字列に要素を追加する。
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 追加する要素。
__append_array_posix() {
set "${1}" "${2-}" ''
until [ "${2#*\'}" '=' "${2}" ]; do
set -- "${1}" "${2#*\'}" "${3}${2%%\'*}'\"'\"'"
done
eval "${1}=\"\${${1}-}\${${1}:+ }'\${3}\${2}'\""
}
### Function: regex_match
##
## 文字列が正規表現に一致するか検査する。
##
## Parameters:
##
## $1 - 検査する文字列。
## $@ - 正規表現。
##
## Returns:
##
## 0か1の真理値。
regex_match() {
awk -- '
BEGIN {
for(i = 2; i < ARGC; i++) {
if(ARGV[1] !~ ARGV[i]) {
exit 1
}
}
exit
}
' ${@+"${@}"} || return 1
return 0
}
### Function: add_option
##
## オプションを追加する
##
## Parameters:
##
## $1 - Debian パッケージ
## $2 - オプションの名前と値
add_option() {
case "${2}" in
*'='*) append_array_posix "${1}" "-${2%%=*}" "${2#*=}";;
*) append_array_posix "${1}" "-${2}";;
esac
}
### Function: deb2dir
##
## Debian パッケージを展開する
##
## Parameters:
##
## $1 - 結果を代入する変数名。
## $2 - 展開先のディレクトリ
deb2dir() (
package="${1}"
dir="${2}"
# Debian パッケージからファイルを取り出す
case "${verboseFlag}" in [!0]*)
printf '# Extract files in %s #\n' "${package}"
esac
dpkg-deb --extract ${prog_v+-v} -- "${package}" "${dir}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(dpkg-deb -W --showformat='${Package}_${Version}_${Architecture}.deb' -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' directory #\\n" "${dir}${controlDir}"
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# Debian パッケージからコントロールファイルを取り出す
case "${verboseFlag}" in [!0]*)
printf "# Extract control files in '%s' #\\n" "${package}"
esac
dpkg-deb --control ${prog_v+-v} -- "${package}" "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}${controlDir}/preinst" ] || [ -x "${dir}${controlDir}/postinst" ] || [ -x "${dir}${controlDir}/prerm" ] || [ -x "${dir}${controlDir}/postrm" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/preinst' ]; then
'${controlDir}/preinst' 'install'
fi
if [ -x '${controlDir}/postinst' ]; then
'${controlDir}/postinst' 'configure' '$(dpkg-deb -W --showformat='${Version}' -- "${package}")'
fi
;;
'stop')
if [ -x '${controlDir}/prerm' ]; then
'${controlDir}/prerm' 'remove'
fi
if [ -x '${controlDir}/postrm' ]; then
'${controlDir}/postrm' 'remove'
fi
;;
__EOF__
fi
esac
)
### Function: pet2dir
##
## Puppy's Extra Treats パッケージを展開する
##
## Parameters:
##
## $1 - PET パッケージ
## $2 - 展開先のディレクトリ
pet2dir() (
package="${1}"
dir="${2}"
basename=$(basename -- "${package}" '.pet')
tmpPet=$(mktemp -d)
cp -f ${prog_v+-v} -- "${package}" "${tmpPet}/package.pet"
if ! pet2tgz "${tmpPet}/package.pet"; then
rm -fr -- "${tmpPet}"
printf "%s: '%s' is broken.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
return 1
fi
# Puppy's Extra Treats パッケージからファイルを取り出す
case "${verboseFlag}" in [!0]*)
printf "# Extract files in '%s' #\\n" "${package}"
esac
tar -xz -C "${tmpPet}" -f "${tmpPet}/package.tar.gz" ${prog_v+-v}
if [ -d "${tmpPet}/${basename}" ]; then
find -- "${tmpPet}/${basename}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}" ';'
fi
rm -fr ${prog_v+-v} -- "${tmpPet}"
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' directory #\\n" "${dir}${controlDir}"
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -x "${dir}/pinstall.sh" ] || [ -x "${dir}/puninstall.sh" ]; then
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/pinstall.sh' ]; then
'${controlDir}/pinstall.sh'
fi
;;
'stop')
if [ -x '${controlDir}/puninstall.sh' ]; then
'${controlDir}/puninstall.sh'
fi
;;
__EOF__
fi
for controlFile in 'pinstall.sh' 'puninstall.sh' 'pet.specs'; do
if [ -f "${dir}/${controlFile}" ]; then
case "${verboseFlag}" in [!0]*)
printf "# Move '%s' files #\\n" "${dir}/${controlFile}"
esac
cp -f ${prog_v+-v} -- "${dir}/${controlFile}" "${dir}${controlDir}"
fi
done
esac
rm -fr ${prog_v+-v} -- "${dir}/pinstall.sh" "${dir}/puinstall.sh" "${dir}/pet.specs"
)
### Function: rpm2dir
##
## RPM パッケージを展開する
##
## Parameters:
##
## $1 - RPM パッケージ
## $2 - 展開先のディレクトリ
rpm2dir() (
package="${1}"
dir="${2}"
# 圧縮ファイルからファイルを取り出す
case "${verboseFlag}" in [!0]*)
printf '# Extract files in %s #\n' "${package}"
esac
rpm2cpio "${1}" | (
cd -- "${2}"
cpio -id --quiet ${prog_v+-v}
)
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' directory #\\n" "${dir}${controlDir}"
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
esac
)
### Function: pkg2dir
##
## Slackware パッケージを展開する
##
## Parameters:
##
## $1 - Slackware パッケージ
## $2 - 展開先のディレクトリ
pkg2dir() (
package="${1}"
dir="${2}"
# 圧縮ファイルからファイルを取り出す
case "${verboseFlag}" in [!0]*)
printf '# Extract files in %s #\n' "${package}"
esac
case "${package}" in
*'.tgz') tar -xz -C "${dir}" -f "${package}" ${prog_v+-v};;
*'.txz') tar -xJ -C "${dir}" -f "${package}" ${prog_v+-v};;
esac
# ${controlFlag} による処理の分岐
case "${controlFlag}" in '1')
filename=$(basename -- "${package}")
controlDir="/var/run/${NAME}/${filename}"
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' directory #\\n" "${dir}${controlDir}"
esac
mkdir -p ${prog_v+-v} -- "${dir}${controlDir}"
# スクリプトの有無により処理を分岐
if [ -f "${dir}/install/doinst.sh" ]; then
chmod ${prog_v+-v} -- '755' "${dir}/install/doinst.sh"
startup_script "${dir}/etc/init.d/${filename}.sh" <<__EOF__
'start')
if [ -x '${controlDir}/doinst.sh' ]; then
'${controlDir}/doinst.sh'
fi
;;
'stop') ;;
__EOF__
fi
case "${verboseFlag}" in [!0]*)
printf "# Move '%s' directory #\\n" "${dir}/install"
esac
if [ -d "${dir}/install" ]; then
find -- "${dir}/install/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dir}${controlDir}" ';'
fi
esac
rm -fr ${prog_v+-v} -- "${dir}/install"
)
### Function: startup_script
##
## サービス起動スクリプトを作成する
##
## Parameters:
##
## $1 - 作成先のファイルパス
startup_script() (
startup="${1}"
basename=$(basename -- "${startup}" '.sh')
basedir=$(dirname -- "${startup}")
shift
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' directory #\\n" "${basedir}"
esac
mkdir -p ${prog_v+-v} -- "${basedir}"
# サービス起動スクリプトを作成
case "${verboseFlag}" in [!0]*)
printf "# Create service startup script in '%s' #\\n" "${startup}"
esac
# サービス起動スクリプトを作成
cat >"${startup}" <<__EOF__
#!/bin/sh
## Startup ${basename} maintainer scripts
#
# @date $(date -u -- '+%Y-%m-%d %H:%M:%S UTC')
# @note Automatically generated by ${NAME} version ${VERSION} (update ${UPDATE})
set -efu
cd -- '/'
case "\${1}" in
$(cat)
'restart')
shift
"\${0}" 'stop' \${@+"\${@}"}
"\${0}" 'start' \${@+"\${@}"}
;;
*)
printf 'Usage: %s {start|stop|restart}\\n' "\${0}" >&2
# EX_USAGE (/usr/include/sysexits.h)
exit '${EX_USAGE}'
;;
esac
__EOF__
# パーミッションを変更し実行が可能に
case "${verboseFlag}" in [!0]*)
printf "# Chenge mod '%s' #\\n" "${startup}"
esac
chmod ${prog_v+-v} -- '755' "${startup}"
)
# @getoptions
parser_definition() {
setup REST abbr:true error:option_error plus:true no:0 help:usage \
-- 'Usage:' " ${2##*/} [OPTION]... DEST [PACKAGE]..." \
'' 'Options:'
option control -c --{no-}control init:@no on:'1-' no: validate:'regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$"' var:'PACKAGE_NUMBER_LIST' -- 'build package control file'
flag dirFlag -d --{no-}directory init:@no -- 'do not make SquashFS but directory'
param :'add_option "options" "${OPTARG}"' -o --option validate:'regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"' var:'NAME[=VALUE]' -- 'option of mksquashfs command'
flag options --no-option init:@no on: no: -- 'reset -o, --option'
flag verboseFlag -v --{no-}verbose init:@no counter:1 -- 'enable verbose output'
disp :usage -h --help -- 'display this help and exit'
disp :'echo "${NAME} ${VERSION}"' -V --version -- 'output version information and exit'
msg -- '' 'Exit Status:' \
' 0 - successful termination' \
' 64 - command line usage error' \
' 65 - data format error' \
' 66 - cannot open input' \
' 67 - addressee unknown' \
' 68 - host name unknown' \
' 69 - service unavailable' \
' 70 - internal software error' \
" 71 - system error (e.g., can't fork)" \
' 72 - critical OS file missing' \
" 73 - can't create (user) output file" \
' 74 - input/output error' \
' 75 - temp failure; user is invited to retry' \
' 76 - remote error in protocol' \
' 77 - permission denied' \
' 78 - configuration error' \
' 129 - received SIGHUP' \
' 130 - received SIGINT' \
' 131 - received SIGQUIT' \
' 143 - received SIGTERM'
msg -- '' 'Examples:' \
" ${2##*/} output.sfs *.deb" \
" ${2##*/} -cv output.sfs *.pet" \
" ${2##*/} -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz" \
" ${2##*/} -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir" \
" ${2##*/} output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'"
}
# @end
# @gengetoptions parser -i parser_definition parse "${1}"
# Generated by getoptions (BEGIN)
# URL: https://github.com/ko1nksm/getoptions (v3.3.0)
control=''
dirFlag='0'
options=''
verboseFlag='0'
REST=''
parse() {
OPTIND=$(($#+1))
while OPTARG= && [ $# -gt 0 ]; do
set -- "${1%%\=*}" "${1#*\=}" "$@"
while [ ${#1} -gt 2 ]; do
case $1 in (*[!a-zA-Z0-9_-]*) break; esac
case '--control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --control"
esac
case '--no-control' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-control"
esac
case '--directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --directory"
esac
case '--no-directory' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-directory"
esac
case '--option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --option"
esac
case '--no-option' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-option"
esac
case '--verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --verbose"
esac
case '--no-verbose' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --no-verbose"
esac
case '--help' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --help"
esac
case '--version' in
"$1") OPTARG=; break ;;
$1*) OPTARG="$OPTARG --version"
esac
break
done
case ${OPTARG# } in
*\ *)
eval "set -- $OPTARG $1 $OPTARG"
OPTIND=$((($#+1)/2)) OPTARG=$1; shift
while [ $# -gt "$OPTIND" ]; do OPTARG="$OPTARG, $1"; shift; done
set "Ambiguous option: $1 (could be $OPTARG)" ambiguous "$@"
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1 ;;
?*)
[ "$2" = "$3" ] || OPTARG="$OPTARG=$2"
shift 3; eval 'set -- "${OPTARG# }"' ${1+'"$@"'}; OPTARG= ;;
*) shift 2
esac
case $1 in
--?*=*) OPTARG=$1; shift
eval 'set -- "${OPTARG%%\=*}" "${OPTARG#*\=}"' ${1+'"$@"'}
;;
--no-*|--without-*) unset OPTARG ;;
-[co]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" "${OPTARG#??}"' ${1+'"$@"'}
;;
-[dvhV]?*) OPTARG=$1; shift
eval 'set -- "${OPTARG%"${OPTARG#??}"}" -"${OPTARG#??}"' ${1+'"$@"'}
OPTARG= ;;
+*) unset OPTARG ;;
esac
case $1 in
'-c'|'--control'|'--no-control')
set -- "$1" "$@"
[ ${OPTARG+x} ] && {
case $1 in --no-*|--without-*) set "noarg" "${1%%\=*}"; break; esac
[ "${OPTARG:-}" ] && { shift; OPTARG=$2; } || OPTARG='1-'
} || OPTARG=''
regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^$|^[1-9][0-9]*(-([1-9][0-9]*)?)?(,[1-9][0-9]*(-([1-9][0-9]*)?)?)*$"; break; }
control="$OPTARG"
shift ;;
'-d'|'--directory'|'--no-directory')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='1' || OPTARG='0'
dirFlag="$OPTARG"
;;
'-o'|'--option')
[ $# -le 1 ] && set "required" "$1" && break
OPTARG=$2
regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$" || { set -- regex_match:$? "$1" regex_match "${OPTARG}" "^[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?(=.*)?$"; break; }
add_option "options" "${OPTARG}"
shift ;;
'--no-option')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG='' || OPTARG=''
options="$OPTARG"
;;
'-v'|'--verbose'|'--no-verbose')
[ "${OPTARG:-}" ] && OPTARG=${OPTARG#*\=} && set "noarg" "$1" && break
eval '[ ${OPTARG+x} ] &&:' && OPTARG=1 || OPTARG=-1
verboseFlag="$((${verboseFlag:-0}+$OPTARG))"
;;
'-h'|'--help')
usage
exit 0 ;;
'-V'|'--version')
echo "${NAME} ${VERSION}"
exit 0 ;;
--)
shift
while [ $# -gt 0 ]; do
REST="${REST} \"\${$(($OPTIND-$#))}\""
shift
done
break ;;
[-+]?*) set "unknown" "$1"; break ;;
*)
REST="${REST} \"\${$(($OPTIND-$#))}\""
esac
shift
done
[ $# -eq 0 ] && { OPTIND=1; unset OPTARG; return 0; }
case $1 in
unknown) set "Unrecognized option: $2" "$@" ;;
noarg) set "Does not allow an argument: $2" "$@" ;;
required) set "Requires an argument: $2" "$@" ;;
pattern:*) set "Does not match the pattern (${1#*:}): $2" "$@" ;;
notcmd) set "Not a command: $2" "$@" ;;
*) set "Validation error ($1): $2" "$@"
esac
option_error "$@" >&2 || exit $?
echo "$1" >&2
exit 1
}
usage() {
cat<<'GETOPTIONSHERE'
Usage:
package2sfs [OPTION]... DEST [PACKAGE]...
Options:
-c, --{no-}control[=PACKAGE_NUMBER_LIST]
build package control file
-d, --{no-}directory do not make SquashFS but directory
-o, --option NAME[=VALUE]
option of mksquashfs command
--no-option reset -o, --option
-v, --{no-}verbose enable verbose output
-h, --help display this help and exit
-V, --version output version information and exit
Exit Status:
0 - successful termination
64 - command line usage error
65 - data format error
66 - cannot open input
67 - addressee unknown
68 - host name unknown
69 - service unavailable
70 - internal software error
71 - system error (e.g., can't fork)
72 - critical OS file missing
73 - can't create (user) output file
74 - input/output error
75 - temp failure; user is invited to retry
76 - remote error in protocol
77 - permission denied
78 - configuration error
129 - received SIGHUP
130 - received SIGINT
131 - received SIGQUIT
143 - received SIGTERM
Examples:
package2sfs output.sfs *.deb
package2sfs -cv output.sfs *.pet
package2sfs -c1,3-4,5- output.sfs pkg1.tgz pkg2.tgz pkg3.tgz pkg4.tgz pkg5.tgz
package2sfs -o b=1048576 -o comp=xz -o Xdict-size=100% output.sfs dir
package2sfs output.sfs 'http://www.example.com/example_1.0.0_i386.sfs'
GETOPTIONSHERE
}
# Generated by getoptions (END)
# @end
parse ${@+"${@}"}
eval "set -- ${REST}"
# コマンドライン引数が不足している
case "${#}" in '0')
printf '%s: Requires an argument: DEST\n' "${0##*/}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_USAGE}"
esac
# コマンド毎に詳細表示を行うか
if [ '2' -le "${verboseFlag}" ]; then
prog_v='1'
fi
# 先頭の位置パラメータから宛先を取り出す
dest="${1}"
shift
# 一時ディレクトリを作成
case "${verboseFlag}" in [!0]*)
printf '# Make temporary directory and temporary file #\n'
esac
awkRangeCheckScript=$(
cat <<-'__EOF__'
BEGIN {
number = ARGV[1]
split(ARGV[2], ranges, ",")
for(i in ranges) {
if(index(ranges[i], "-")) {
split(ranges[i], array, "-")
if(array[1] != "" && array[2] != "" && array[2] < array[1]) {
tmp = array[1]
array[1] = array[2]
array[2] = tmp
}
if((array[1] == "" || array[1] <= number) && (array[2] == "" || number <= array[2])) {
exit
}
} else if(ranges[i] == number) {
exit
}
}
exit 1
}
__EOF__
)
tmpDir=$(mktemp -d)
tmpContent="${tmpDir}/content"
tmpDownload="${tmpDir}/download"
tmpPackage="${tmpDir}/package"
mkdir -p ${prog_v+-v} -- "${tmpContent}" "${tmpDownload}" "${tmpPackage}"
# 各パッケージを処理
for package in ${@+"${@}"}; do
index=$((${index:-0} + 1))
controlFlag='0'
if awk -- "${awkRangeCheckScript}" "${index}" "${control}"; then
controlFlag='1'
fi
# URL ならばタウンロード
case "${package}" in 'http://'*/* | 'https://'*/* | 'ftp://'*/*)
filename=$(basename -- "${package}")
case "${verboseFlag}" in [!0]*)
printf "# Download '%s' #\\n" "${package}"
esac
if command -v 'wget' >'/dev/null'; then
wget --no-verbose --output-document "${tmpDownload}/${filename}" ${prog_v+-v} -- "${package}"
elif command -v 'curl' >'/dev/null'; then
curl --compressed --fail --location --output "${tmpDownload}/${filename}" --silent --show-error ${prog_v+-v} -- "${package}"
else
printf "'wget' or 'curl' is required.\\n" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_UNAVAILABLE}"
fi
package="${tmpDownload}/${filename}"
esac
# 読み込みの許可がない
if [ '!' -r "${package}" ]; then
printf "%s: No permission to read '%s'.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_NOINPUT}"
# ディレクトリ
elif [ -d "${package}" ]; then
case "${verboseFlag}" in [!0]*)
printf "# Copy files in '%s' #\\n" "${package}"
esac
find -- "${package}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
continue
elif [ '!' -f "${package}" ]; then
printf "%s: '%s' is not a regular file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
fi
# パッケージファイルの種類によって処理を分岐
case "${package}" in
# Debian パッケージ
*[!./]'.deb') deb2dir "${package}" "${tmpContent}";;
# Puppy's Extra Treats
*[!./]'.pet') pet2dir "${package}" "${tmpPackage}";;
# RPM パッケージ
*[!./]'.rpm') rpm2dir "${package}" "${tmpPackage}";;
# Slackware GZIP or Slackware XZ
*[!./]'.tgz' | *[!./]'.txz') pkg2dir "${package}" "${tmpPackage}";;
# イメージファイル (ext2, ext3, ext4) と SquashFS ファイル
*[!./].[234]fs | *[!./]'.sfs')
case "${verboseFlag}" in [!0]*)
printf "# Mount '%s' #\\n" "${package}"
esac
case "${package}" in
*[!./].[234]fs) mount -o 'loop' -r -t 'ext2,ext3,ext4' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
*[!./]'.sfs') mount -r -t 'squashfs' ${prog_v+-v} -- "${package}" "${tmpPackage}";;
esac
case "${verboseFlag}" in [!0]*)
printf "# Copy the files in '%s' #\\n" "${package}"
esac
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
case "${verboseFlag}" in [!0]*)
printf "# Unmount '%s' #\\n" "${package}"
esac
umount -d ${prog_v+-v} -- "${tmpPackage}"
;;
# 互換性のないファイル
*)
printf "%s: '%s' is not a compatible file.\\n" "${0##*/}" "${package}" >&2
printf "Try '%s' for more information.\\n" "${0##*/} --help" >&2
end_call "${EX_DATAERR}"
;;
esac
# 解凍したファイルをメインのディレクトリに移動
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}" ';'
find -- "${tmpPackage}/" -path '*[!/]' -prune -exec rm -fr ${prog_v+-v} -- '{}' '+'
done
# 一部ディレクトリの内容を上位ディレクトリに移動
for path in '/lib/i386-linux-gnu' '/usr/bin/i386-linux-gnu' '/usr/lib/i386-linux-gnu'; do
if [ -d "${tmpContent}${path}" ]; then
case "${verboseFlag}" in [!0]*)
printf "# Move '%s' #\\n" "${path}"
esac
find -- "${tmpContent}${path}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${tmpContent}${path%/*}" ';'
rm -fr ${prog_v+-v} -- "${tmpContent}${path}"
fi
done
# ${dirFlag} による処理の分岐
case "${dirFlag}" in
'1')
# 一時ディレクトリの内容を ${dest} にコピー
case "${verboseFlag}" in [!0]*)
printf "# Copy temporary directory to '%s' #\\n" "${dest}"
esac
mkdir -p ${prog_v+-v} -- "${dest}"
find -- "${tmpContent}/" -path '*[!/]' -prune -exec cp -fRP ${prog_v+-v} -- '{}' "${dest}" ';'
;;
*)
# SquashFS ファイルを作成
case "${verboseFlag}" in [!0]*)
printf "# Make '%s' #\\n" "${dest}"
esac
eval 'mksquashfs "${tmpContent}" "${dest}"' "${options}"
;;
esac
- ディレクトリ
- Debian パッケージ (*.deb)
- PET パッケージ (*.pet)
- RPM パッケージ (*.rpm)
- Slackware パッケージ (*.tgz, *.txz)
- SquashFS(SFS) ファイル (*.sfs)
- ext2, ext3, ext4 のイメージファイル (*.2fs, *.3fs, *.4fs)
*.txz が処理できないバグを修正しました。バージョンは2.2.1になりました。
2024年01月11日追記
'/lib/i386-linux-gnu', '/usr/bin/i386-linux-gnu', '/usr/lib/i386-linux-gnu' における処理を少し改善しました。これで 'devx_precise_5.7.1.sfs' などを正常に展開できます。バージョンは2.2.2になりました。
Lenovo G550(CPU: Intel Celeron 900 @ 2.20GHz, RAM: 971MB, HDD: 149.05GiB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP
🖥HITACHI FLORA 310 DL7(CPU: Intel Pentium III 700 MHz, RAM:512MB) + Precise-571JP