# opkhelper
# lib/control
# Functions for parsing control files.
#
# Copyright (C) 2012 Patrick "P. J." McDermott
#
# This program 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.
#
# This program 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 this program. If not, see .
[ -n "${_OH_CONTROL_SH}" ] && return 0
_OH_CONTROL_SH=true
. @@LIBDIR@@/messages
. @@LIBDIR@@/locale
. @@LIBDIR@@/util
# Constant global parameters:
OH_CONTROL_SOURCE_FIELDS_REQUIRED='Maintainer'
OH_CONTROL_SOURCE_FIELDS_OPTIONAL='Build-Depends Homepage'
OH_CONTROL_BINARY_FIELDS_REQUIRED='Architecture Platform Priority Description'
OH_CONTROL_BINARY_FIELDS_OPTIONAL='Essential Depends Recommends Suggests '\
'Pre-Depends Conflicts Provides Replaces'
OH_CONTROL_SOURCE_FIELD_MAINTAINER=
OH_CONTROL_SOURCE_FIELD_BUILD_DEPENDS=
OH_CONTROL_SOURCE_FIELD_HOMEPAGE=
OH_CONTROL_BINARY_FIELD_ARCHITECTURE=
OH_CONTROL_BINARY_FIELD_PLATFORM=
OH_CONTROL_BINARY_FIELD_PRIORITY=
OH_CONTROL_BINARY_FIELD_DESCRIPTION=
OH_CONTROL_BINARY_FIELD_ESSENTIAL=
OH_CONTROL_BINARY_FIELD_DEPENDS=
OH_CONTROL_BINARY_FIELD_RECOMMENDS=
OH_CONTROL_BINARY_FIELD_SUGGESTS=
OH_CONTROL_BINARY_FIELD_PRE_DEPENDS=
OH_CONTROL_BINARY_FIELD_CONFLICTS=
OH_CONTROL_BINARY_FIELD_PROVIDES=
OH_CONTROL_BINARY_FIELD_REPLACES=
oh_control_parse_source()
{
_control_parse "${OH_SOURCE_DIR}/control" 'SOURCE'
}
oh_control_parse_binary()
{
_control_parse "${OH_SOURCE_DIR}/${1}.pkg/control" 'BINARY'
}
oh_control_gen_source()
{
_old_package="${OH_CONTROL_BINARY_FIELD_PACKAGE}"
_old_version="${OH_BINARY_VERSION}"
_old_architecture="${OH_CONTROL_BINARY_FIELD_ARCHITECTURE}"
_old_recommends="${OH_CONTROL_BINARY_FIELD_RECOMMENDS}"
_old_description="${OH_CONTROL_BINARY_FIELD_DESCRIPTION}"
OH_CONTROL_BINARY_FIELD_PACKAGE="src:${OH_SOURCE}"
OH_BINARY_VERSION="${OH_SOURCE_VERSION}"
OH_CONTROL_BINARY_FIELD_ARCHITECTURE='all'
OH_CONTROL_BINARY_FIELD_RECOMMENDS="${OH_CONTROL_SOURCE_FIELD_BUILD_DEPENDS}"
OH_CONTROL_BINARY_FIELD_DESCRIPTION="${OH_SOURCE} source package"
_control_gen 'SOURCE' \
"src:${OH_SOURCE}.control/control" "src:${OH_SOURCE}.data"
OH_CONTROL_BINARY_FIELD_PACKAGE="${_old_package}"
OH_BINARY_VERSION="${_old_version}"
OH_CONTROL_BINARY_FIELD_ARCHITECTURE="${_old_architecture}"
OH_CONTROL_BINARY_FIELD_RECOMMENDS="${_old_recommends}"
OH_CONTROL_BINARY_FIELD_DESCRIPTION="${_old_description}"
}
oh_control_gen_binary()
{
_control_gen 'BINARY' \
"${1}.control/control" "${1}.data"
}
_control_parse()
{
_control="${1}"
_type="${2}"
_req=" $(eval echo \$\{OH_CONTROL_"${_type}"_FIELDS_REQUIRED\}) "
_opt=" $(eval echo \$\{OH_CONTROL_"${_type}"_FIELDS_OPTIONAL\}) "
_all="${_req}${_opt}"
_got=' '
# Initialize fields.
for _name in ${_all}; do
_param="OH_CONTROL_${_type}_FIELD_$(echo "${_name}" | \
LC_CTYPE=C tr '[:lower:]-' '[:upper:]_')"
eval "${_param}="
done
_param=
_line_nr=0
while IFS= read -r _line; do
_line_nr=$(($_line_nr + 1))
if [ "${_line# }" = "${_line}" ]; then
# "Name: Value" line.
_name="${_line%%:*}"
_value="${_line#*: }"
if [ -z "${_name}" -o "${_name}" = "${_line}" \
-o -z "${_value}" ]; then
# Badly formatted control field.
_control_parse_error "${_control}" "${_line_nr}" \
"${oh_str_control_bad_nv}"
continue
fi
if [ "${_all% ${_name} *}" = "${_all}" ]; then
# Unknown field.
_control_parse_error "${_control}" "${_line_nr}" \
"${oh_str_control_unknown_field}" \
"${_name}"
else
# Remove field from list of required fields.
_req="$(echo "${_req}" | sed "s/${_name}//")"
fi
if [ "${_got% ${_name} }" != "${_got}" ]; then
# Duplicate field.
_control_parse_error "${_control}" "${_line_nr}" \
"${oh_str_control_duplicate_field}" \
"${_field}"
else
_got="${_got}${_field} "
fi
_param="OH_CONTROL_${_type}_FIELD_$(echo "${_name}" | \
LC_CTYPE=C tr '[:lower:]-' '[:upper:]_')"
# Escape the value.
_value="$(echo "${_value}" | sed "s/'/'\\\\''/g")"
eval "${_param}='${_value}'"
else
# Continuation line.
if [ -z "${_param}" ]; then
# Expecting a "Name: Value" line.
_control_parse_error "${_control}" "${_line_nr}" \
"${oh_str_control_found_continuation}"
continue
fi
_value="${_line# }"
_value="$(echo "${_value}" | sed "s/'/'\\\\''/g")"
eval "${_param}='${_param}
${_value}'"
fi
done <"${_control}"
_req="${_req## }"
_req="${_req%% }"
if [ -n "${_req}" ]; then
# Missing required control fields.
_control_parse_error "${_control}" 0 \
"${oh_str_control_missing_fields}" \
"$(echo "${_req}" | sed 's/ / /g' | \
sed "s/ /${oh_str_list_item_separator}/g")"
fi
}
_control_parse_error()
{
_file="${1}"
_line_nr="${2}"
_error="${3}"
shift 3
if [ "${_line_nr}" -eq 0 ]; then
_file_info=$(printf '%20s:' "${_file}")
else
_file_info=$(printf '%20s(l%d):' "${_file}" "${_line_nr}")
fi
oh_warn "${_file_info} ${_error}" "${@}"
}
_control_gen()
{
_type="${1}"
_control="${2}"
_data="${3}"
# TODO: Handle platforms and architectures like "any" and "any-linux-any".
# 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:
#
#
#
_sizes="$(find "${_data}" -type f -exec wc -c '{}' ';' | cut -d ' ' -f 1)"
_inst_size=0
for _size in ${_sizes}; do
_inst_size=$(($_inst_size + $_size))
done
# 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;
# TODO: Further investigate opkg's disk space calculation and, if necessary,
# patch opkg and submit a bug report.
_inst_size=$((($_inst_size + 1023) / 1024))
mkdir -p "${_control%/*}"
cat >"${_control}" <>"${_control}"
fi
done
cat >>"${_control}" <>"${_control}"
fi
}