# Generate a control directory with a control file and scripts # # Copyright (C) 2012, 2019, 2023-2024 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 doc_pkg_q= 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_q="$(ob_qualify_package_name "${doc_pkg}" "${OPK_HOST_ARCH}")" if [ x"$(ob_get_binary_parameter "${doc_pkg}" 'Architecture')" \ = x'all' ]; then doc_dep="${doc_pkg_q} (= ${OPK_SOURCE_VERSION})" elif [ x"$(ob_get_binary_parameter "${binary}" 'Architecture')" \ = x'all' ]; then doc_dep="${doc_pkg_q} (>= ${OPK_SOURCE_VERSION}), $(: \ )${doc_pkg_q} (<< ${OPK_SOURCE_VERSION}.~)" else doc_dep="${doc_pkg_q} (= ${OPK_BINARY_VERSION})" fi 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_q}" ]; 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 }