# Generate a control directory with a control file and scripts
#
# Copyright (C) 2012, 2019 Patrick McDermott
#
# This file is part of opkbuild.
#
# opkbuild is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# opkbuild is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with opkbuild. If not, see .
set -eu
calc_inst_size()
{
local binary="${1}"
shift 1
local inst_size=
local sizes=
local size=
# Calculate installed size.
# Don't use du, since that considers the allocated size of files,
# symbolic links, and directories (i.e. actual file sizes plus the
# filesystem overhead on the build system).
# See the following for more information:
#
#
#
inst_size=0
if [ -d "${binary}.data" ]; then
sizes="$(find "${binary}.data" -type f -exec wc -c '{}' ';' | \
cut -d ' ' -f 1)"
for size in ${sizes}; do
inst_size=$((${inst_size} + ${size}))
done
fi
# Convert bytes to kibibytes and round up.
# Note: There is an inconsistency between the Debian Policy Manual and
# opkg in the units of this field. Debian Policy defines this field in
# units of kibibytes:
# The disk space is given as the integer value of the estimated
# installed size in bytes, divided by 1024 and rounded up.
# However, opkg apparently attempts to convert this value from bytes to
# kibibytes in its determination of whether the package's data will fit
# on the system:
# pkg_size_kbs = (pkg->installed_size + 1023)/1024;
# (from libopkg/opkg_install.c line 245)
# (still in upstream as of 2019-02-25, libopkg/opkg_install.c:118)
# In other words, if a package declares an installed size of 10 KiB,
# opkg checks for 10 MiB of available space.
# TODO: Further investigate opkg's disk space calculation and, if
# necessary, patch opkg and submit a bug report.
printf '%d' $(((${inst_size} + 1023) / 1024))
}
gen_control_src()
{
local binary=
local name=
local value=
local deps=
local dep=
local homepage=
binary="src:${OPK_SOURCE}"
mkdir -p -- "${binary}.control"
exec 3>"${binary}.control/control"
cat >&3 <<-EOF
Package: src:${OPK_SOURCE}
Source: ${OPK_SOURCE}
Binary:$(printf '%s\n' $(ob_get_binary_packages) | \
LC_ALL='C' sort | xargs printf ' %s')
Version: ${OPK_SOURCE_VERSION}
Architecture: src
Platform: all
Maintainer: $(ob_get_source_parameter 'Maintainer' | \
tr '\n' ' ')
EOF
for name in Build-Depends; do
value="$(ob_get_source_parameter "${name}")"
if [ -z "${value}" ]; then
continue
fi
deps=''
IFS=','
for dep in ${value}; do
unset IFS
deps="${deps}$(ob_parse_dep "${dep}"), "
done
unset IFS
value="$(ob_substvars "${deps}")"
printf '%s: %s\n' "${name}" "${deps}" | sed 's/[, ]*$//' >&3
done
cat >&3 <<-EOF
Installed-Size: $(calc_inst_size "src:${OPK_SOURCE}")
Format: $(ob_get_source_parameter 'Format')
Description: ${OPK_SOURCE} source package
EOF
homepage="$(ob_get_source_parameter 'Homepage')"
if [ -n "${homepage}" ]; then
printf '%s: %s\n' 'Homepage' "${homepage}" >&3
fi
exec 3>&-
return 0
}
gen_control_bin()
{
local binary="${1}"
local version="${2}"
local arch="${3}"
local plat="${4}"
local desc="${5}"
shift 5
local binary_qual=
local value=
local doc_pkg=
local upstream_ver=
local doc_dep=
local name=
local homepage=
mkdir -p -- "${binary}.control"
exec 3>"${binary}.control/control"
binary_qual="$(ob_qualify_package_name "${binary}" "${OPK_HOST_ARCH}")"
cat >&3 <<-EOF
Package: ${binary_qual}
Source: ${OPK_SOURCE}
Version: ${version}
Architecture: ${arch}
Platform: ${plat}
EOF
value="$(ob_get_binary_parameter "${binary}" 'Section')"
if [ -n "${value}" ]; then
cat >&3 <<-EOF
Section: ${value}
EOF
fi
cat >&3 <<-EOF
Maintainer: $(ob_get_source_parameter 'Maintainer' | \
tr '\n' ' ')
EOF
if ! doc_pkg="$(ob_get_doc_package)"; then
ob_error "$(ob_get_msg 'cant_get_doc_pkg')"
return 1
fi
doc_pkg="$(ob_qualify_package_name "${doc_pkg}" "${OPK_HOST_ARCH}")"
if ! ob_parse_version -u upstream_ver "${OPK_SOURCE_VERSION}"; then
ob_error "$(ob_get_msg 'bad_source_version')"
return 1
fi
doc_dep="${doc_pkg} (>= ${upstream_ver}), $(: \
)${doc_pkg} (<= ${upstream_ver}-z)"
for name in Essential Depends Recommends Suggests Pre-Depends \
Conflicts Provides Replaces; do
value="$(ob_get_binary_parameter "${binary}" "${name}")"
if [ x"${name}" = x'Depends' ] &&
[ x"${binary_qual}" != x"${doc_pkg}" ]; then
value="${doc_dep}, ${value}"
fi
if [ -z "${value}" ]; then
continue
fi
case "${name}" in
'Essential')
;;
'Depends' | 'Recommends' | 'Suggests' | 'Pre-Depends')
value="$(ob_substvars "${value}" "${binary}")"
value="$(ob_reduce_deps \
-a "${OPK_HOST_ARCH}" \
-p "${OPK_HOST_PLAT}" \
-- "${value}")"
;;
'Conflicts' | 'Provides' | 'Replaces')
value="$(ob_substvars "${value}" "${binary}")"
value="$(ob_reduce_deps \
-a "${OPK_HOST_ARCH}" \
-p "${OPK_HOST_PLAT}" \
-u -- "${value}")"
;;
esac
printf '%s: %s\n' "${name}" "${value}" | sed 's/[, ]*$//' >&3
done
cat >&3 <<-EOF
Installed-Size: $(calc_inst_size "${binary}")
Description:$(printf '%s' "${desc}" | sed 's/^/ /')
EOF
homepage="$(ob_get_source_parameter 'Homepage')"
if [ -n "${homepage}" ]; then
printf '%s: %s\n' 'Homepage' "${homepage}" >&3
fi
exec 3>&-
return 0
}
install_maintainer_scripts()
{
local binary="${1}"
shift 1
local script=
local target=
for script in preinst postinst prerm postrm; do
if [ -L "../${binary}.pkg/${script}" ]; then
target="$(ls -l "../${binary}.pkg/${script}")"
target="${target#* -> }"
ln -s -- "${target}" "${binary}.control/${script}"
elif [ -r "../${binary}.pkg/${script}" ]; then
cp "../${binary}.pkg/${script}" \
"${binary}.control/${script}"
chmod 755 "${binary}.control/${script}"
fi
done
return 0
}
gen_conffiles()
{
local binary="${1}"
shift 1
if [ -d "${binary}.data/etc" ]; then
find "${binary}.data/etc" -type f | sed "s@^${binary}.data@@" \
>"${binary}.control/conffiles"
if [ -z "$(head -n 1 "${binary}.control/conffiles")" ]; then
rm -f -- "${binary}.control/conffiles"
else
chmod 644 "${binary}.control/conffiles"
fi
fi
return 0
}
gen_md5sums()
{
local binary="${1}"
shift 1
local has_data=
local sum=
local file=
has_data=false
exec 3>"${binary}.control/md5sums"
while read -r sum file; do
case "${file}" in '-') continue;; esac
file="${file#${binary}.data}"
printf '%s %s\n' "${sum}" "${file}" >&3
has_data=true
done <<-EOF
$(find "${binary}.data" -type f 2>/dev/null | sort | \
xargs md5sum)
EOF
exec 3>&-
if ! ${has_data}; then
rm -f -- "${binary}.control/md5sums"
else
chmod 644 "${binary}.control/md5sums"
fi
return 0
}
main()
{
local pkg=
local arch=
local plat=
local desc=
if ! ob_set_text_domain 'opkbuild'; then
printf '%s: Error: Failed to load locale messages\n' \
"${0##*/}" >&2
return 1
fi
ob_init_package '..' || return 1
if [ x"${OB_DO_SOURCE:+set}" = x'set' ]; then
ob_info "$(ob_get_msg 'gen_control')" "src:${OPK_SOURCE}"
gen_control_src
gen_md5sums "src:${OPK_SOURCE}"
else
for pkg in ${OPK_PACKAGES_REDUCED}; do
ob_info "$(ob_get_msg 'gen_control')" "${pkg}"
ob_set_package_substvars "${pkg}"
arch="$(ob_get_binary_parameter "${pkg}" \
'Architecture')"
[ x"${arch}" != x'all' ] && arch="${OPK_HOST_ARCH}"
plat="$(ob_get_binary_parameter "${pkg}" 'Platform')"
[ x"${plat}" != x'all' ] && plat="${OPK_HOST_PLAT}"
desc="$(ob_get_binary_parameter "${pkg}" 'Description')"
desc="$(ob_substvars "${desc}" "${pkg}")"
gen_control_bin "${pkg}" "${OPK_BINARY_VERSION}" \
"${arch}" "${plat}" "${desc}"
install_maintainer_scripts "${pkg}"
gen_conffiles "${pkg}"
gen_md5sums "${pkg}"
done
fi
return 0
}