#!/bin/bash # Magellan Linux Installer Functions (mage.functions.sh) # $Header: /home/cvsd/magellan-cvs/magellan-src/mage/usr/lib/mage/mage4.functions.sh,v 1.29 2007-03-27 16:35:57 niro Exp $ mage_setup() { [ ! -d ${MROOT}${INSTALLDB} ] && \ install -d ${MROOT}${INSTALLDB} [ ! -f ${MROOT}${VIRTUALDB_FILE} ] && \ touch ${MROOT}${VIRTUALDB_FILE} [ ! -d ${PKGDIR} ] && install -d ${PKGDIR} [ ! -d ${BUILDDIR} ] && install -d ${BUILDDIR} [ ! -d ${MAGEDIR} ] && install -d ${MAGEDIR} return 0 } unpack_packages() { local list="$@" local magefile local pkg local pkgtype local count_current local count_total # get count of total packages declare -i count_current=0 declare -i count_total=0 for i in ${list}; do (( count_total++ )); done for magefile in ${list} do pkg="$(get_value_from_magefile PKGNAME ${magefile}).${PKGSUFFIX}" pkgtype="$(get_value_from_magefile PKGTYPE ${magefile})" (( count_current++ )) xtitle "[ (${count_current}/${count_total}) Unpacking ${pkg} ]" # abort on virtual pkg if [[ ${pkgtype} = virtual ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !unpack virtual (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi # abort on sources pkg if [[ ${pkgtype} = sources ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !unpack sources (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi echo -e " ${COLBLUE}***${COLDEFAULT} unpacking (${count_current}/${count_total}): ${pkg} ... " tar xjmf ${PKGDIR}/${pkg} -C ${BUILDDIR} || die "Unpacking package ${pkg}" done # add a crlf for a better view if [ ${count_total} -gt 1 ]; then echo; fi } # fix_mtime path/to/$mtime/reffile $pathto/file # creates a given reference file and fixes given file # returns new mtime fix_mtime() { local reference="$1" local pathto="$2" local mtime mtime=$(stat -c %Y "${reference}") touch \ --no-create \ --time=mtime \ --reference "${reference}" \ "${pathto}" echo "${mtime}" } # fix_descriptor pkgname/.dir "foo1" "foo2" fix_descriptor() { local descriptor="$1" local output local i shift for i in $@ do if [[ -z ${output} ]] then output="${i}" else output="${output}§${i}" fi done echo "${output}" >> ${BUILDDIR}/${descriptor}_fixed } ################################################### # function install_direcories # # install_direcories $PKGNAME # ################################################### install_directories() { local pkgname="$1" local pathto local posix local user local group local IFS # sanity checks; abort if not given [ -z "${pkgname}" ] && die "install_directories() \$pkgname not given." # check needed global vars [ -z "${BUILDDIR}" ] && die "install_directories() \$BUILDDIR not set." [ ! -f ${BUILDDIR}/${pkgname}/.dirs ] && die "install_directories() .dirs not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix user group do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t>>> DIR: ${MROOT}${pathto}" # monitors /etc/env.d -> env-rebuild [[ ${pathto} = /etc/env.d ]] && export MAGE_ENV_REBUILD=true # monitors /usr/share/info -> info-rebuild [[ ${pathto} = /usr/share/info ]] && export MAGE_INFO_REBUILD=true install -m "${posix}" -o "${user}" -g "${group}" -d "${MROOT}${pathto}" done < ${BUILDDIR}/${pkgname}/.dirs # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function install_files # # install_files $PKGNAME # ################################################### install_files() { local pkgname="$1" local pathto local posix local user local group local mtime local md5sum local retval local counter local filename local dest_dirname local dest_protected local IFS # sanity checks; abort if not given [ -z "${pkgname}" ] && die "install_files() \$pkgname not given." # check needed global vars [ -z "${BUILDDIR}" ] && die "install_files() \$BUILDDIR not set." [ ! -f ${BUILDDIR}/${pkgname}/.files ] && die "install_files() .files not found" # delete old files [ -f ${BUILDDIR}/${pkgname}/.files_fixed ] && rm ${BUILDDIR}/${pkgname}/.files_fixed # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix user group mtime md5sum do [ -z "${pathto}" ] && continue # final destination dir of file ${pathto} dest_dirname="$(dirname "${MROOT}${pathto}")" ### small hotfix fix ### [ ! -d "${dest_dirname}" ] && install -d "${dest_dirname}" # check if the file is config_protected # ${MROOT} will automatically added if set !! is_config_protected "${pathto}" retval="$?" # 0 - not protected # # 1 - error # # 2 - protected # # 3 - protected but masked # case ${retval} in # file is not protected - (over)write it 0|3) [[ ${VERBOSE} = on ]] && echo -e "\t>>> FILE: ${MROOT}${pathto}" install -m "${posix}" -o "${user}" -g "${group}" \ ${BUILDDIR}/${pkgname}/binfiles/"${pathto}" \ "${MROOT}${pathto}" # fix mtime and db fix_descriptor ${pkgname}/.files \ "${pathto}" \ "${posix}" \ "${user}" \ "${group}" \ "$(fix_mtime "${BUILDDIR}/${pkgname}"/.mtime \ "${MROOT}${pathto}")" \ "${md5sum}" ;; # file is protected, write backup file 2) if [[ ${VERBOSE} = on ]] then echo -en "${COLRED}" echo -n "! prot " echo -en "${COLDEFAULT}" echo " === FILE: ${MROOT}${pathto}" fi filename="$(basename "${pathto}")" counter=$(count_protected_files "${pathto}") dest_protected="${dest_dirname}/._cfg${counter}_${filename}" install -m "${posix}" -o "${user}" -g "${group}" \ ${BUILDDIR}/${pkgname}/binfiles/"${pathto}" \ "${dest_protected}" # fix mtime and db fix_descriptor ${pkgname}/.files \ "${pathto}" \ "${posix}" \ "${user}" \ "${group}" \ "$(fix_mtime "${BUILDDIR}/${pkgname}"/.mtime \ "${dest_protected}")" \ "${md5sum}" # update global MAGE_PROTECT_COUNTER (( MAGE_PROTECT_COUNTER++ )) export MAGE_PROTECT_COUNTER ;; esac done < ${BUILDDIR}/${pkgname}/.files # now copy the fixed file over the old one [ -f ${BUILDDIR}/${pkgname}/.files_fixed ] && \ cp ${BUILDDIR}/${pkgname}/.files{_fixed,} # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function install_symlinks # # install_symlinks $PKGNAME # ################################################### install_symlinks() { local pkgname="$1" local pathto local posix local link local mtime local IFS # sanity checks; abort if not given [ -z "${pkgname}" ] && die "install_symlinks() \$pkgname not given." # check needed global vars [ -z "${BUILDDIR}" ] && die "install_symlinks() \$BUILDDIR not set." [ ! -f ${BUILDDIR}/${pkgname}/.symlinks ] && die "install_symlinks() .symlinks not found" # delete old files [ -f ${BUILDDIR}/${pkgname}/.symlinks_fixed ] && rm ${BUILDDIR}/${pkgname}/.symlinks_fixed # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix link mtime do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t>>> LINK: ${MROOT}${pathto}" ln -snf "${link}" "${MROOT}${pathto}" # fix mtime and db fix_descriptor ${pkgname}/.symlinks \ "${pathto}" \ "${posix}" \ "${link}" \ "$(fix_mtime "${BUILDDIR}/${pkgname}"/.mtime \ "${MROOT}${pathto}")" done < ${BUILDDIR}/${pkgname}/.symlinks # now copy the fixed file over the old one [ -f ${BUILDDIR}/${pkgname}/.symlinks_fixed ] && \ cp -f ${BUILDDIR}/${pkgname}/.symlinks{_fixed,} # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function install_blockdevices # # install_blockdevices $PKGNAME # ################################################### install_blockdevices() { local pkgname="$1" local pathto local posix local IFS # sanity checks; abort if not given [ -z "${pkgname}" ] && die "install_blockdevices() \$pkgname not given." # check needed global vars [ -z "${BUILDDIR}" ] && die "install_blockdevices() \$BUILDDIR not set." [ ! -f ${BUILDDIR}/${pkgname}/.pipes ] && die "install_blockdevices() .pipes not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t>>> PIPE: ${MROOT}${pathto}" mkfifo -m "${posix}" "${MROOT}$pathto" done < ${BUILDDIR}/${pkgname}/.pipes # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function install_characterdevices # # install_characterdevices $PKGNAME # ################################################### install_characterdevices() { local pkgname="$1" local pathto local posix local major local minor local IFS # sanity checks; abort if not given [ -z "${pkgname}" ] && die "install_characterdevices() \$pkgname not given." # check needed global vars [ -z "${BUILDDIR}" ] && die "install_characterdevices() \$BUILDDIR not set." [ ! -f ${BUILDDIR}/${pkgname}/.char ] && die "install_characterdevices() .char not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix major minor do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t>>> CHAR: ${MROOT}${pathto}" mknod -m ${posix} "${MROOT}${pathto}" c ${major} ${minor} done < ${BUILDDIR}/${pkgname}/.char # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function build_doinstall # # build_doinstall $PKGNAME # # NOTE: this is an wrapper do install packages # ################################################### build_doinstall() { local pkgname="$1" # sanity checks; abort if not given [ -z "${pkgname}" ] && die "build_doinstall() \$pkgname not given." # this is only a wrapper # NOTE: # !! we use § as field seperator !! # doing so prevent us to get errors by filenames with spaces # create a new mtime reference file touch ${BUILDDIR}/${pkgname}/.mtime install_directories ${pkgname} || die "install directories ${pkgname}" install_files ${pkgname} || die "install files ${pkgname}" install_symlinks ${pkgname} || die "install symlinks ${pkgname}" install_blockdevices ${pkgname} || die "install blockdevices ${pkgname}" install_characterdevices ${pkgname} || die "install chardevices ${pkgname}" } ################################################### # function install_database_entry # # install_database_entry $PKGNAME $PKGTYPE # # PKGTYPE can be "virtual", "sources" or nothing # ################################################### install_database_entry() { local pcat local pname local pver local pbuild local pkgtype local pkgname local magefile local dbrecorddir local provide local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; --pkgname|-a) shift; pkgname="$1" ;; --pkgtype|-t) shift; pkgtype="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "install_database_entry() \$pcat not given." [ -z "${pname}" ] && die "install_database_entry() \$pname not given." [ -z "${pver}" ] && die "install_database_entry() \$pver not given." [ -z "${pbuild}" ] && die "install_database_entry() \$pbuild not given." [ -z "${pkgname}" ] && die "install_database_entry() \$pkgname not given." # check needed global vars [ -z "${MAGEDIR}" ] && die "install_database_entry() \$MAGEDIR not set." [ -z "${INSTALLDB}" ] && die "install_database_entry() \$INSTALLDB not set." # set needed vars magefile="${MAGEDIR}/${pcat}/${pname}/${pname}-${pver}-${pbuild}.mage" dbrecorddir="${MROOT}${INSTALLDB}/${pcat}/${pname}-${pver}-${pbuild}" # abort if mage file not exists [ ! -f ${magefile} ] && die "install_database_entry() ${magefile} not exist." # add package to database install -d ${dbrecorddir} # install mage-file to database install -m 0644 -o root -g root ${magefile} ${dbrecorddir} # create fake file descriptors # used by virtual and source packages for i in .dirs .symlinks .files .pipes .char do touch ${dbrecorddir}/${i} done # put the category to database echo ${pcat} > ${dbrecorddir}/.categorie # now install PKGTYPE specific files case ${pkgtype} in virtual) touch ${dbrecorddir}/.virtual ;; sources) touch ${dbrecorddir}/.sources ;; *) # !move! .mtime to database (only mv modifies not the mtime!!) mv ${BUILDDIR}/${pkgname}/.mtime ${dbrecorddir}/.mtime # normal packages needs these files local i for i in .char .dirs .files .pipes .symlinks do install -m 0644 ${BUILDDIR}/${pkgname}/${i} \ ${dbrecorddir}/${i} done ;; esac # last but not least register virtuals provide="$(get_value_from_magefile PROVIDE ${magefile})" if [ -n "${provide}" ] then for i in ${provide} do virtuals_add "${i}" "${pcat}/${pname}" done fi } ################################################### # function remove_database_entry # # remove_database_entry $PKGNAME $PKGTYPE # # PKGTYPE can be "virtual", "sources" or nothing # ################################################### remove_database_entry() { local pcat local pname local pver local pbuild local magefile local dbrecorddir local provide local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_database_entry() \$pcat not given." [ -z "${pname}" ] && die "remove_database_entry() \$pname not given." [ -z "${pver}" ] && die "remove_database_entry() \$pver not given." [ -z "${pbuild}" ] && die "remove_database_entry() \$pbuild not given." # check needed global vars [ -z "${INSTALLDB}" ] && die "remove_database_entry() \$INSTALLDB not set." # set needed vars magefile="${MROOT}${INSTALLDB}/${pcat}/${pname}-${pver}-${pbuild}/${pname}-${pver}-${pbuild}.mage" dbrecorddir="${MROOT}${INSTALLDB}/${pcat}/${pname}-${pver}-${pbuild}" # abort if mage file not exists [ ! -f ${magefile} ] && die "remove_database_entry() ${magefile} not exist." # remove virtuals only if no other exist if [[ $(count_installed_pkgs --pcat ${pcat} --pname ${pname}) -le 1 ]] then # first unregister virtuals provide="$(get_value_from_magefile PROVIDE ${magefile})" if [ -n "${provide}" ] then for i in ${provide} do virtuals_del "${i}" "${pcat}/${pname}" done fi fi # removes database entry if [ -d ${dbrecorddir} ] then rm -rf ${dbrecorddir} fi } # get the number of installed packages count_installed_pkgs() { local pcat local pname local pkg local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "pkg_count() \$pcat not given." [ -z "${pname}" ] && die "pkg_count() \$pname not given." declare -i i=0 for pkg in $(get_uninstall_candidates --pcat ${pcat} --pname ${pname}) do (( i++ )) #echo "$i ${pkg}" done # return the value echo "${i}" } ################################################### # function compare_mtime # # compare_mtime $pcat/$PKGNAME /path/to/file # # # # returns: # # 0=delete me # # 1=keep me # # # # compares mtime of given files in packages # ################################################### compare_mtime() { local pfull="$1" local pathto="$2" local mtime local pcat local x mtime="$(stat -c %Y ${MROOT}${INSTALLDB}/${pfull}/.mtime)" # if $pathto is a symlink than compare linked binary if [ -L "${MROOT}${pathto}" ] then # readlink -f resolves full path of linked file x="$(readlink -f "${MROOT}${pathto}")" # abort if target does not exists # we keep safe here, theoretically the link can removed [ ! -e "${x}" ] && return 1 x=$(stat -c %Y "${x}") else x=$(stat -c %Y "${MROOT}${pathto}") fi [[ ${mtime} = ${x} ]] && return 0 # echo "keep me : ${pathto}" return 1 } ################################################### # function remove_symlinks # # remove_symlinks $PKGNAME # ################################################### remove_symlinks() { local pathto local posix local link local mtime local IFS local retval local pcat local pname local pver local pbuild local i local pfull IFS=$'\n' # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_symlinks() \$pcat not given." [ -z "${pname}" ] && die "remove_symlinks() \$pname not given." [ -z "${pver}" ] && die "remove_symlinks() \$pver not given." [ -z "${pbuild}" ] && die "remove_symlinks() \$pbuild not given." pfull="${pcat}/${pname}-${pver}-${pbuild}" # check needed global vars [ -z "${BUILDDIR}" ] && die "remove_symlinks() \$BUILDDIR not set." [ ! -f ${MROOT}${INSTALLDB}/${pfull}/.symlinks ] && die "remove_symlinks() .symlinks not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix link mtime do [ -z "${pathto}" ] && continue if [ ! -L "${MROOT}${pathto}" ] then [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! exist${COLDEFAULT} === LINK: ${MROOT}${pathto}" continue fi # *no* ${MROOT}, will be set internal compare_mtime "${pfull}" "${pathto}" retval=$? # 0=delete me # # 1=keep me # case ${retval} in 0) [[ ${VERBOSE} = on ]] && echo -e "\t<<< LINK: ${MROOT}${pathto}" rm "${MROOT}${pathto}" ;; 1) [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! mtime${COLDEFAULT} === LINK: ${MROOT}${pathto}" ;; esac done < ${MROOT}${INSTALLDB}/${pfull}/.symlinks # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function remove_files # # remove_files $PKGNAME # ################################################### remove_files() { local pathto local posix local user local group local mtime local md5sum local IFS local retval local pcat local pname local pver local pbuild local i local pfull IFS=$'\n' # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_symlinks() \$pcat not given." [ -z "${pname}" ] && die "remove_symlinks() \$pname not given." [ -z "${pver}" ] && die "remove_symlinks() \$pver not given." [ -z "${pbuild}" ] && die "remove_symlinks() \$pbuild not given." pfull="${pcat}/${pname}-${pver}-${pbuild}" # check needed global vars [ -z "${BUILDDIR}" ] && die "remove_files() \$BUILDDIR not set." [ ! -f ${MROOT}${INSTALLDB}/${pfull}/.files ] && die "remove_files() .files not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix user group mtime md5sum do [ -z "${pathto}" ] && continue if [ ! -e "${MROOT}${pathto}" ] then [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! exist${COLDEFAULT} === FILE: ${MROOT}${pathto}" continue fi # *no* ${MROOT}, will be set internal compare_mtime "${pfull}" "${pathto}" retval=$? # 0=delete me # # 1=keep me # case ${retval} in 0) # check if the file is config_protected # ${MROOT} will automatically added if set !! is_config_protected "${pathto}" retval="$?" # 0 - not protected # # 1 - error # # 2 - protected # # 3 - protected but masked # case ${retval} in # file is not protected - delete it 0|3) [[ ${VERBOSE} = on ]] && echo -e "\t<<< FILE: ${MROOT}${pathto}" rm "${MROOT}${pathto}" ;; # file is protected, do not delete 2) if [[ ${VERBOSE} = on ]] then echo -en "${COLRED}" echo -n "! prot " echo -en "${COLDEFAULT}" echo " === FILE: ${MROOT}${pathto}" fi ;; esac ;; 1) [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! mtime${COLDEFAULT} === FILE: ${MROOT}${pathto}" ;; esac done < ${MROOT}${INSTALLDB}/${pfull}/.files # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function remove_blockdevices # # remove_blockdevices $PKGNAME # ################################################### remove_blockdevices() { local pathto local posix local IFS local pcat local pname local pver local pbuild local i local pfull IFS=$'\n' # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_symlinks() \$pcat not given." [ -z "${pname}" ] && die "remove_symlinks() \$pname not given." [ -z "${pver}" ] && die "remove_symlinks() \$pver not given." [ -z "${pbuild}" ] && die "remove_symlinks() \$pbuild not given." pfull="${pcat}/${pname}-${pver}-${pbuild}" # check needed global vars [ -z "${BUILDDIR}" ] && die "remove_blockdevices() \$BUILDDIR not set." [ ! -f ${MROOT}${INSTALLDB}/${pfull}/.pipes ] && die "remove_blockdevices() .pipes not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t<<< PIPE: ${MROOT}${pathto}" rm "${MROOT}${pathto}" done < ${MROOT}${INSTALLDB}/${pfull}/.pipes # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function remove_characterdevices # # remove_characterdevices $PKGNAME # ################################################### remove_characterdevices() { local pathto local posix local IFS local pcat local pname local pver local pbuild local i local pfull IFS=$'\n' # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_symlinks() \$pcat not given." [ -z "${pname}" ] && die "remove_symlinks() \$pname not given." [ -z "${pver}" ] && die "remove_symlinks() \$pver not given." [ -z "${pbuild}" ] && die "remove_symlinks() \$pbuild not given." pfull="${pcat}/${pname}-${pver}-${pbuild}" # check needed global vars [ -z "${BUILDDIR}" ] && die "remove_characterdevices() \$BUILDDIR not set." [ ! -f ${MROOT}${INSTALLDB}/${pfull}/.char ] && die "remove_characterdevices() .char not found" # sets fieldseperator to "§" instead of " " IFS=§ while read pathto posix do [ -z "${pathto}" ] && continue [[ ${VERBOSE} = on ]] && echo -e "\t<<< CHAR: ${MROOT}${pathto}" rm "${MROOT}${pathto}" done < ${MROOT}${INSTALLDB}/${pfull}/.char # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function remove_direcories # # remove_direcories $PKGNAME # ################################################### remove_directories() { local pathto local posix local IFS local pcat local pname local pver local pbuild local i local pfull IFS=$'\n' # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "remove_symlinks() \$pcat not given." [ -z "${pname}" ] && die "remove_symlinks() \$pname not given." [ -z "${pver}" ] && die "remove_symlinks() \$pver not given." [ -z "${pbuild}" ] && die "remove_symlinks() \$pbuild not given." pfull="${pcat}/${pname}-${pver}-${pbuild}" # check needed global vars [ -z "${BUILDDIR}" ] && die "remove_directories() \$BUILDDIR not set." [ ! -f ${MROOT}${INSTALLDB}/${pfull}/.char ] && die "remove_directories() .dirs not found" # sets fieldseperator to "§" instead of " " IFS=§ # reversed order is mandatory ! tac ${MROOT}${INSTALLDB}/${pfull}/.dirs | while read pathto posix do [ -z "${pathto}" ] && continue if [ ! -d "${MROOT}${pathto}" ] then [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! exist${COLDEFAULT} === DIR: ${MROOT}${pathto}" continue fi # exclude .keep directories if [ -f "${MROOT}${pathto}/.keep" ] then [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! .keep${COLDEFAULT} === DIR: ${MROOT}${pathto}" continue fi # monitors /etc/env.d -> env-rebuild [[ ${pathto} = /etc/env.d ]] && export MAGE_ENV_REBUILD=true # monitors /usr/share/info -> info-rebuild [[ ${pathto} = /usr/share/info ]] && export MAGE_INFO_REBUILD=true if rmdir "${MROOT}${pathto}" &> /dev/null then [[ ${VERBOSE} = on ]] && echo -e "\t<<< DIR: ${MROOT}${pathto}" else [[ ${VERBOSE} = on ]] && \ echo -e "${COLRED}! empty${COLDEFAULT} === DIR: ${MROOT}${pathto}" fi done # very important: unsetting the '§' fieldseperator IFS=$'\n' } ################################################### # function build_douninstall # # build_douninstall $PKGNAME # # NOTE: this is an wrapper do remove packages # ################################################### build_douninstall() { local pcat local pname local pver local pbuild local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "build_douninstall() \$pcat not given." [ -z "${pname}" ] && die "build_douninstall() \$pname not given." [ -z "${pver}" ] && die "build_douninstall() \$pver not given." [ -z "${pbuild}" ] && die "build_douninstall() \$pbuild not given." # this is only a wrapper # NOTE: # !! we use § as field seperator !! # doing so prevent us to get errors by filenames with spaces for i in symlinks files blockdevices characterdevices directories do remove_${i} \ --pcat "${pcat}" \ --pname "${pname}" \ --pver "${pver}" \ --pbuild "${pbuild}" \ || die "remove ${i} ${pcat}/${pname}-${pver}-${pbuild}" done } # fetch_packages /path/to/mage/file1 /path/to/mage/file2 fetch_packages() { local list="$@" local pkg local mirr local magefile local md5file local opt local count_current local count_total [ -z "${MIRRORS}" ] && die "You have no mirrors defined. Please edit your ${MAGERC}." # get count of total packages declare -i count_current=0 declare -i count_total=0 for i in ${list}; do (( count_total++ )); done for magefile in ${list} do pkg="$(get_value_from_magefile PKGNAME ${magefile}).${PKGSUFFIX}" pkgtype="$(get_value_from_magefile PKGTYPE ${magefile})" (( count_current++ )) xtitle "[ (${count_current}/${count_total}) Fetching ${pkg} ]" # abort on virtual pkg if [[ ${pkgtype} = virtual ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !fetch virtual (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi # abort on sources pkg if [[ ${pkgtype} = sources ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !fetch sources (${count_current}/${count_total}): ${pkg/.${PKGSUFFIX}/} ... " continue fi # abort if already exist if [ -f ${PKGDIR}/${pkg} ] then echo -ne " ${COLBLUE}***${COLDEFAULT}" echo " fetch complete (${count_current}/${count_total}): ${pkg} ... " continue fi for mirr in ${MIRRORS} do echo -ne " ${COLBLUE}***${COLDEFAULT}" #echo -e " fetching (${count_current}/${count_total}): ${mirr}/${pkg} ... " echo -e " fetching (${count_current}/${count_total}): ${pkg} ... " [[ ${VERBOSE} = off ]] && opt="--quiet" wget \ --passive-ftp \ --tries 3 \ --continue \ --progress bar \ --directory-prefix=${PKGDIR} \ ${opt} ${mirr}/${PACKAGES_SERVER_PATH}/${pkg} if [[ $? = 0 ]] then break else continue fi done if [ ! -f ${PKGDIR}/${pkg} ] then die "Could not download ${pkg}" fi done # add a crlf for a better view if [ ${count_total} -gt 1 ]; then echo; fi } syncmage() { if [ -z "${RSYNC}" ] then die "You have no rsync-mirrors defined. Please edit your ${MAGERC}." fi local i for i in ${RSYNC} do rsync ${RSYNC_FETCH_OPTIONS} ${i} ${MAGEDIR} if [[ $? = 0 ]] then break else continue fi done # clean up backup files (foo~) find ${MAGEDIR} -name *~ -exec rm '{}' ';' # check if an newer mage version is available is_newer_mage_version_available } cleanpkg() { if [ -d "${PKGDIR}" ] then echo -n "Removing downloaded packages... " rm -rf ${PKGDIR}/* echo "done." fi } xtitle() { if [[ ${TERM} = xterm ]] then echo -ne "\033]0;Mage: $1\007" fi return 0 } xtitleclean() { if [[ ${TERM} = xterm ]] then echo -ne "\033]0;\007" fi return 0 } # cuts full pathnames or versioniezed names down to basename choppkgname() { #we want this only if full name was used if [ -n "$(echo ${MAGENAME}|fgrep .mage)" ] then #cuts ARCH and PBUILD #ARCH comes from ${MAGERC} MAGENAME=$(echo ${MAGENAME} |sed -e "s:-${ARCH}-r*.::g") #cuts version number MAGENAME=$(basename ${MAGENAME%-*} .mage) fi } # get_categorie $PNAME, returns CATEGORIE # $1=pname # ret 0=ok, 1=not_found pname2pcat() { local pname="$1" local repo="$2" local pcat local categorie for pcat in ${MAGEDIR}/* do if [ -d ${pcat}/${pname} ] then categorie=$(basename ${pcat}) fi done echo "${categorie}" } # check_stable_package /path/to/foo.mage # returns 0=stable 1=unstable check_stable_package() { # first check if this magefile is not blacklisted blacklisted "$1" || return 1 local STATE STATE="$(get_value_from_magefile STATE "$1")" # state testing if [[ ${USE_TESTING} = true ]] || [[ ${MAGE_DISTRIBUTION} = testing ]] then case ${STATE} in testing|stable) return 0 ;; *) return 1 ;; esac fi # state unstable if [[ ${USE_UNSTABLE} = true ]] || [[ ${MAGE_DISTRIBUTION} = unstable ]] then case ${STATE} in unstable|testing|stable) return 0 ;; *) return 1 ;; esac fi # no use_state given = stable case ${STATE} in stable) return 0 ;; *) return 1 ;; esac } # get_highest_magefile ${PCAT} ${PNAME} # fake at moment returns only stable pkgs (must set to be one) # return $HIGHEST_MAGEFILE get_highest_magefile() { local HIGHEST_MAGEFILE local PCAT="$1" local PNAME="$2" local magefile for magefile in $(ls --format=single-column -v ${MAGEDIR}/${PCAT}/${PNAME}/*) do # we exclude subdirs (for stuff like a md5sum dir) [ -d ${magefile} ] && continue if check_stable_package ${magefile} then HIGHEST_MAGEFILE=${magefile} #for debug only [[ ${MAGEDEBUG} = on ]] && echo "HIGHEST_MAGEFILE=${HIGHEST_MAGEFILE}" fi done # do not so anything # # stop here if HIGHEST_MAGEFILE is zero # # this package must be unstable or old # if [ -z "${HIGHEST_MAGEFILE}" ] # then # echo # echo -n "All packages named " # echo -en ${COLRED}\""${PKGNAME%-*-*-*}\""${COLDEFAULT} # echo -n " are marked " # echo -en ${COLRED}"*UNSTABLE*"${COLDEFAULT} # echo "." # echo "You need to declare USE_UNSTABLE=true to install this." # echo # echo "Example:" # echo " USE_UNSTABLE=true mage install ${PKGNAME%-*-*-*}" # echo # echo "Be warned that these packages are not stable and may cause serious problems." # echo "You should know what you are doing, so don't complain about any damage." # echo # return 1 # fi echo "${HIGHEST_MAGEFILE}" return 0 } ################################################### # function is_config_protected # # is_config_protected /path/to/file # # # # returns: # # 0 - not protected # # 1 - error # # 2 - protected # # 3 - protected but masked # # # ################################################### is_config_protected() { local EXPFILE local TEST local PROTECTED local IFS EXPFILE="${MROOT}$1" # file does not exist; it can be written [ ! -e ${EXPFILE} ] && return 0 # to be safe; it may be '§' IFS=' ' # check ob in config protect for i in ${CONFIG_PROTECT} do # ersetzen von $i nur wenn am anfang der variable TEST="${EXPFILE/#${MROOT}${i}/Protected}" if [ "${TEST}" != "${EXPFILE}" ] then # setzen das es protected ist PROTECTED=TRUE # check ob nicht doch maskiert for x in ${CONFIG_PROTECT_MASK} do TEST="${EXPFILE/#${MROOT}${x}/Protect_Masked}" if [ "${TEST}" != "${EXPFILE}" ] then PROTECTED=MASKED fi done fi done unset IFS case ${PROTECTED} in TRUE) #echo "I'm protected" return 2 ;; MASKED) #echo "I'm protected, but masked - delete me" return 3 ;; *) #echo "delete me" return 0 ;; esac } ################################################### # function count_protected_files # # count_protected_files /path/to/file # # # # note: prints number of protected files # # exp: 0012 # ################################################### count_protected_files() { ${MLIBDIR}/writeprotected "$1" } # call with # 'get_uninstall_candidates (--pcat cat --protected pcat/pfull) --pname PNAME' # returns /path/to/magefile(s) get_uninstall_candidates() { local search_pname local pkg local pcat local pname local pver local pbuild local list local pcatdir local protected local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcatdir="$1" ;; --pname|-n) shift; search_pname="$1" ;; --protected|-p) shift; protected="$1" ;; esac shift done # it's not good to complain here about empty pnames; better to continue later anyway # # sanity checks; abort if not given # [ -z "${search_pname}" ] && die "get_uninstall_candidates() \$search_pname not given." # check needed global vars [ -z "${INSTALLDB}" ] && die "get_uninstall_candidates() \$INSTALLDB not set." # set pcatdir to '*' if empty [ -z "${pcatdir}" ] && pcatdir='*' for pkg in ${MROOT}${INSTALLDB}/${pcatdir}/* do # abort if not a dir [ ! -d ${pkg} ] && continue pname="$(magename2pname ${pkg})" if [[ ${search_pname} = ${pname} ]] then pcat="$(magename2pcat ${pkg} installdb)" pver="$(magename2pver ${pkg})" pbuild="$(magename2pbuild ${pkg})" # exclude proteced [[ ${protected} = ${pcat}/${pname}-${pver}-${pbuild} ]] && continue list="${list} ${pcat}/${pname}-${pver}-${pbuild}" fi done echo "${list}" } # reads virtualdb file #$1 = virtualname; $2 commands: showpkgs, showline #return 0 == installed -> shows installed pkg as well #return 1 == not installed virtuals_read() { local virtualname="$1" local command="$2" local virtline local line x i # parse file to get virtual_name line IFS=$'\n' for line in $(< ${MROOT}${VIRTUALDB_FILE}) do IFS=$' ' for x in ${line} do if [[ ${x} = ${virtualname} ]] then virtline="${line}" [[ ${command} = showline ]] && echo "${line}" fi done IFS=$'\n' done unset IFS # now read the packages linked to VIRTUAL_NAME and output them if [ -n "${virtline}" ] then if [[ ${command} = showpkgs ]] then declare -i x=0 for i in ${virtline} do if [ ${x} -ge 1 ] then echo "${i}" fi ((x++)) done fi return 0 fi return 1 } #add pkg to virtualdb # $1 == virtualname $2= pkgname # retvals: 0=ok,added; 1=error; 3=pkg already in virtual virtuals_add() { local virtualname="$1" local pkgname="$2" local oldline local line i local installed_file local OLDIFS if virtuals_read ${virtualname} then # make sure ${PKG_NAME} is *not* in ${VIRTUAL_NAME} already for i in $(virtuals_read ${virtualname} showpkgs) do if [[ ${i} = ${pkgname} ]] then echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "${pkgname} already linked as ${virtualname} ..." #return 3 return 0 fi done echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo "updating ${virtualname} entry with ${pkgname} ..." oldline="$(virtuals_read ${virtualname} showline)" # make a backup mv ${MROOT}${VIRTUALDB_FILE} ${MROOT}${VIRTUALDB_FILE}.old OLDIFS="${IFS}" IFS=$'\n' for line in $(< ${MROOT}${VIRTUALDB_FILE}.old) do # if the right line, append ${pkgname}, else do nothing if [[ ${line} = ${oldline} ]] then echo "${line} ${pkgname}" >> ${MROOT}${VIRTUALDB_FILE} else echo "${line}" >> ${MROOT}${VIRTUALDB_FILE} fi done # unset IFS IFS="${OLDIFS}" else echo -ne "${COLBLUE} >>> ${COLDEFAULT}" echo "register ${pkgname} as ${virtualname} ..." echo "${virtualname} ${pkgname}" >> ${MROOT}${VIRTUALDB_FILE} fi return 0 } #deletes pakages from virtual database #$1 virtualname; $2 pkgname virtuals_del() { local virtualname="$1" local pkgname="$2" local oldline local method local line i x local pkg_installed local OLDIFS # first check if exists if virtuals_read ${virtualname} then # get method -> delall or update and check if ${PKG_NAME} exists in ${VIRTUAL_NAME} declare -i x=0 for i in $(virtuals_read ${virtualname} showpkgs) do if [[ ${i} = ${pkgname} ]] then pkg_installed=true fi ((x++)) done # abort if not installed if [[ ${pkg_installed} != true ]] then echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "${pkgname} does not exists in ${virtualname}." return 0 fi if [ ${x} -ge 2 ] then method=update else method=delall fi # get the complete line oldline="$(virtuals_read ${virtualname} showline)" # make a backup of the db mv ${VIRTUALDB_FILE} ${VIRTUALDB_FILE}.old # parse virtualdb OLDIFS="${IFS}" IFS=$'\n' for line in $(< ${VIRTUALDB_FILE}.old) do if [[ ${line} = ${oldline} ]] then #delall or update? case ${method} in update) echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo "Unlinking ${pkgname} from ${virtualname} in virtual database ..." # del PKG_NAME from line echo "${line/ ${pkgname}/}" >> ${VIRTUALDB_FILE} ;; delall) echo -ne "${COLBLUE} <<< ${COLDEFAULT}" echo "Deleting ${virtualname} in virtual database ..." # continue; do not write anything continue ;; esac else echo "${line}" >> ${VIRTUALDB_FILE} fi done # unset IFS IFS="${OLDIFS}" else echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "${virtualname} does not exists in virtual database." fi } # gets real pkgname from virtuals.default #$1=VIRTUAL_NAME; returns PKG_NAME default_virtualname_to_pkgname() { local VIRTUAL_NAME PKG_NAME db_virtualname db_pkgname VIRTUAL_NAME=$1 while read db_virtualname db_pkgname do if [ "${db_virtualname}" == "${VIRTUAL_NAME}" ] then PKG_NAME="${db_pkgname}" fi done << EOF $(< ${VIRTUALDB_DEFAULTS}) EOF if [ -n "${PKG_NAME}" ] then echo "${PKG_NAME}" fi } minclude() { local i if [[ -n $* ]] then for i in $* do [[ ${MAGEDEBUG} = on ]] && \ echo "--- Including ${MAGEDIR}/include/${i}.minc" source ${MAGEDIR}/include/${i}.minc done [[ ${MAGEDEBUG} = on ]] && echo fi } sminclude() { local i if [[ -n $* ]] then for i in $* do echo "--- Including ${SMAGESCRIPTSDIR}/include/${i}.sminc" source ${SMAGESCRIPTSDIR}/include/${i}.sminc done echo fi } # checks if an newer mage version is available is_newer_mage_version_available() { local newest_mage local installed_mage newest_mage="$(basename $(get_highest_magefile app-mage mage) .mage)" installed_mage="$(magequery -n mage | cut -d' ' -f5)" if [[ ${newest_mage} > ${installed_mage} ]] then echo echo -en ${COLRED}"An update for your packetmanager is available. "${COLDEFAULT} echo -e ${COLBLUE}"[ ${newest_mage} ]"${COLDEFAULT} echo "It is recommened to install this newer version" echo "or your current system installation may break." echo echo -en "Please update mage by running " echo -e ${COLGREEN}"'mage install mage'"${COLDEFAULT} echo fi } # returns pname from pkgname # pkgname2pname $PKGNAME pkgname2pname() { local pname pname="${1%-*-*-*}" echo "${pname}" } # returns pver from pkgname # pkgname2pver $PKGNAME pkgname2pver() { local i pver i="${1/$(pkgname2pname $1)-/}" pver="${i%-*-*}" echo "${pver}" } # returns pbuild from pkgname # pkgname2pbuild $PKGNAME pkgname2pbuild() { local pbuild pbuild="${1##*-}" echo "${pbuild}" } # returns parch from pkgname # pkgname2parch $PKGNAME pkgname2parch() { local i x parch i="${1%-*-*}-" x="${1%-*}" parch="${x/${i}/}" echo "${parch}" } # returns pname from magename # magename2pname /PATH/TO/MAGE/FILE magename2pname() { local i pname i="$(basename $1 .mage)" pname="${i%-*-*}" echo "${pname}" } # returns pver from magename # magename2pver /PATH/TO/MAGE/FILE magename2pver() { local i pver i="$(basename $1 .mage)" i="${i/$(magename2pname $1)-/}" pver="${i%-*}" echo "${pver}" } # returns pbuild from magename # magename2pbuild /PATH/TO/MAGE/FILE magename2pbuild() { local i pbuild i="$(basename $1 .mage)" pbuild="${i##*-}" echo "${pbuild}" } # returns pcat from magename # magename2pcat /PATH/TO/MAGE/FILE magename2pcat() { local i pcat if [[ ${2} = installdb ]] then # go 1 dir back i="${1%/*}" else # go 2 dirs back i="${1%/*/*}" fi # get basename pcat="${i##*/}" echo "${pcat}" } # returns pcat from DEPEND (without operand ! PCAT/PNAME-VERSION) # dep2pcat DEPEND dep2pcat() { local pcat pcat="${1%/*}" echo "${pcat}" } # returns pname from DEPEND (without operand ! PCAT/PNAME-VERSION) # $2=virtual is used to resolv VDEPEND from virtual packages # dep2pcat DEPEND (virtual) dep2pname() { local pname pname="${1##*/}" # cut version only if not virtual or it will cut the name if [[ $(dep2pcat $1) != virtual ]] && \ [[ $2 != virtual ]] then pname="${pname%-*}" fi echo "${pname}" } dep2highest_magefile() { local pcat local pname local magefile local installed_virtuals pcat="$(dep2pcat $1)" pname="$(dep2pname $1)" if [[ ${pcat} = virtual ]] then # first check if virtual is already installed installed_virtuals="$(virtuals_read ${pcat}/${pname} showpkgs)" if [ -n "${installed_virtuals}" ] then for vpkg in ${installed_virtuals} do realpkgname="${vpkg}" virtualpkgname="${pcat}/${pname}" pcat="$(dep2pcat ${realpkgname})" pname="$(dep2pname ${realpkgname} virtual)" done else # choose one from virtualdb defaults (virtuals.defaults) realpkgname="$(default_virtualname_to_pkgname ${pcat}/${pname})" virtualpkgname="${pcat}/${pname}" pcat="$(dep2pcat ${realpkgname})" pname="$(dep2pname ${realpkgname} virtual)" fi fi magefile="$(get_highest_magefile ${pcat} ${pname})" echo "${magefile}" } # is_installed ${PCAT}/${PNAME}-${PVER}-${PBUILD} is_installed() { local fullpkgname="$1" # return 0 if installed [ -d ${MROOT}${INSTALLDB}/${fullpkgname} ] && return 0 return 1 } install_packages() { local list="$@" local pkg local pcat local pname local pver local pbuild local total_pkgs local current_pkg local src_install local uninstall_list # check for --src-install if [[ $1 = --src-install ]] then # remove --src-install from list list=${list/--src-install/} # enable src-install src_install="--src-install" fi # reset MAGE_PROTECT_COUNTER declare -i MAGE_PROTECT_COUNTER=0 export MAGE_PROTECT_COUNTER # get count of total packages declare -i total_pkgs=0 declare -i current_pkg=0 for i in ${list}; do (( total_pkgs++ )); done echo if [[ -n ${MROOT} ]] then echo -ne ${COLRED} echo "!! installing in MROOT=${MROOT}" echo -ne ${COLDEFAULT} echo fi for pkg in ${list} do (( current_pkg++ )) pcat=$(magename2pcat ${pkg}) pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) mage_install \ --pcat ${pcat} \ --pname ${pname} \ --pver ${pver} \ --pbuild ${pbuild} \ --count-total ${total_pkgs} \ --count-current ${current_pkg} \ ${src_install} # check for allready installed packages and remove them # except the package we have installed uninstall_list="$(get_uninstall_candidates \ --pcat "${pcat}" \ --pname "${pname}" \ --protected ${pcat}/${pname}-${pver}-${pbuild})" # uninstall all packges in uninstall_list if not empty if [ -n "${uninstall_list}" ] then echo uninstall_packages ${uninstall_list} \ || die "install_packges() uninstalling not-needed." fi # crlf for better view in VERBOSE mode #if [[ ${VERBOSE} = on ]]; then echo; fi echo done #echo "DEBUG MAGE_PROTECT_COUNTER=${MAGE_PROTECT_COUNTER}" show_etc_update_mesg } # get_value_from_magefile VARIABLE # returns the content of this VAR get_value_from_magefile() { local var="$1" local magefile="$2" local value [[ -z ${var} ]] && return 1 [[ -z ${magefile} ]] && return 1 # local all possible vars of a mage file # to prevent bad issues local PKGNAME local STATE local DESCRIPTION local HOMEPAGE local DEPEND local SDEPEND local PROVIDE local PKGTYPE local preinstall local postinstall local preremove local postremove # sanity checks [ -f ${magefile} ] && source ${magefile} || \ die "get_value_from_magefile: ${magefile} not found." [ -z "${var}" ] && die "get_value_from_magefile: \$var not given." source ${magefile} eval value=\$$(echo ${var}) echo "${value}" # unset these functions unset -f preinstall unset -f postinstall unset -f preremove unset -f postremove } mage_install() { # local all possible vars of a mage file # to prevent bad issues local PKGNAME local STATE local DESCRIPTION local HOMEPAGE local DEPEND local SDEPEND local PROVIDE local PKGTYPE local preinstall local postinstall local preremove local postremove local pcat local pname local pver local pbuild local count_total local count_current local magefile local src_install # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; --count-total) shift; count_total="$1" ;; --count-current) shift; count_current="$1" ;; --src-install|-s) shift; src_install=true ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "mage_install() \$pcat not given." [ -z "${pname}" ] && die "mage_install() \$pname not given." [ -z "${pver}" ] && die "mage_install() \$pver not given." [ -z "${pbuild}" ] && die "mage_install() \$pbuild not given." # check needed global vars [ -z "${MAGEDIR}" ] && die "mage_install() \$MAGEDIR not set." [ -z "${INSTALLDB}" ] && die "mage_install() \$INSTALLDB not set." [ -z "${BUILDDIR}" ] && die "mage_install() \$BUILDDIR not set." xtitle "[ (${count_current}/${count_total}) Installing ${pcat}/${pname}-${pver}-${pbuild} ]" echo -ne "${COLBLUE} >>> ${COLDEFAULT}" echo -n "installing (${count_current}/${count_total}): " echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" echo -e "${COLGREEN}${pname}-${pver}-${pbuild}${COLDEFAULT}" magefile="${MAGEDIR}/${pcat}/${pname}/${pname}-${pver}-${pbuild}.mage" source ${magefile} # abort on sources if no srcinstall if [[ ${PKGTYPE} = sources ]] && [[ ${src_install} != true ]] then echo echo -e "This Package is a Source Package." echo echo -e "Only 'srcinstall' works with this type of packages" echo -en "If you have done a srcinstall before, " echo -e "you will find the files in /usr/src." echo exit 1 fi ## preinstall scripts if [ -n "$(typeset -f preinstall)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running preinstall ... " preinstall unset preinstall fi if [[ ${src_install} = true ]] then local smage2file # check needed global vars [ -z "${SMAGESCRIPTSDIR}" ] && die "\$SMAGESCRIPTSDIR not set." [ -z "${SOURCEDIR}" ] && die "\$SOURCEDIR not set." [ -z "${BINDIR}" ] && die "\$BINDIR not set." # build the package first if [[ ${MAGEDEBUG} = on ]] then echo M:${pname} echo V:${pver} echo B:${pbuild} fi smage2file=${SMAGESCRIPTSDIR}/${pname}/${pname}-${pver}-${pbuild}.smage2 if [ -f "${smage2file}" ] then echo -e " ${COLBLUE}***${COLDEFAULT} building package from source ... " smage2 ${smage2file} || die "compile failed" else echo echo "$(basename ${SMAGEFILE}) not found." echo "update your smage-tree and try it again." echo die fi fi if [[ ${PKGTYPE} != virtual ]] && \ [[ ${PKGTYPE} != sources ]] then echo -e " ${COLBLUE}***${COLDEFAULT} merging files into system ... " build_doinstall ${PKGNAME} fi ## postinstall scripts if [ -n "$(typeset -f postinstall)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running postinstall ... " postinstall unset postinstall fi # install a database entry install_database_entry \ --pcat "${pcat}" \ --pname "${pname}" \ --pver "${pver}" \ --pbuild "${pbuild}" \ --pkgname "${PKGNAME}" \ --pkgtype "${PKGTYPE}" \ || die "error in mage_install() running install_database_entry()." # remove the package dir now if [ -d ${BUILDDIR}/${PKGNAME} ] then rm -rf ${BUILDDIR}/${PKGNAME} fi # rebuilds toplevel info node if [[ ${MAGE_INFO_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding top-level info node ... " ${MLIBDIR}/mkinfodir ${MROOT}/usr/share/info \ > ${MROOT}/usr/share/info/dir && \ echo "done." || echo "failure." unset MAGE_INFO_REBUILD fi # rebuilds the enviroment with the content of /etc/env.d if [[ ${MAGE_ENV_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding environment ... " ${MLIBDIR}/env-rebuild.sh > /dev/null && \ echo "done." || echo "failure." unset MAGE_ENV_REBUILD fi xtitleclean echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -n "package " # echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" # echo -ne "${COLGREEN}${pname}-${pver}-${pbuild}${COLDEFAULT} " echo "successfully installed." # unset these functions unset -f preinstall unset -f postinstall unset -f preremove unset -f postremove } md5sum_packages() { local list="$@" local magefile local pcat local pname local pkgname local pkgfile local pkgtype local count_current local count_total # get count of total packages declare -i count_current=0 declare -i count_total=0 for i in ${list}; do (( count_total++ )); done for magefile in ${list} do pcat=$(magename2pcat ${magefile}) pname=$(magename2pname ${magefile}) pkgname="$(get_value_from_magefile PKGNAME ${magefile})" md5file="${MAGEDIR}/${pcat}/${pname}/md5/${pkgname}.md5" pkgfile="$(get_value_from_magefile PKGNAME ${magefile}).${PKGSUFFIX}" pkgtype="$(get_value_from_magefile PKGTYPE ${magefile})" (( count_current++ )) xtitle "[ (${count_current}/${count_total}) MD5SUM: ${pkgfile} ]" # abort on virtual pkg if [[ ${pkgtype} = virtual ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !md5sum virtual (${count_current}/${count_total}): ${pkgfile/.${PKGSUFFIX}/} ... " continue fi # abort on sources pkg if [[ ${pkgtype} = sources ]] then echo -ne " ${COLBLUE}---${COLDEFAULT}" echo " !md5sum sources (${count_current}/${count_total}): ${pkgfile/.${PKGSUFFIX}/} ... " continue fi if [ -f "${md5file}" ] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -ne "checking md5sum (${count_current}/${count_total}): " ( cd ${PKGDIR}; md5sum --check ${md5file}) || die "md5 for ${pkgfile} failed" else echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -e "!! no md5sum file found for ${pkgfile} :(" fi done # add a crlf for a better view if [ ${count_total} -gt 1 ]; then echo; fi } ## uninstall_packages ulist uninstall_packages() { local list="$@" local pcat local pname local pver local pbuild local can_pcat local can_pname local can_ver_list if [[ -n ${MROOT} ]] then echo -ne ${COLRED} echo "!! uninstalling from MROOT=${MROOT}" echo -ne ${COLDEFAULT} echo fi # generate a candidates list for pkg in ${list} do pcat=$(dep2pcat ${pkg}) pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) can_pcat="${pcat}" can_pname="${pname}" if [ -z "${can_ver_list}" ] then can_ver_list=" ${pver}-${pbuild}" else can_ver_list="${can_ver_list}, ${pver}-${pbuild}" fi done echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "following candidate(s) will be removed:" echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -ne "${COLBOLD}${can_pcat}/${can_pname}:${COLDEFAULT}" echo -e "${COLRED} ${can_ver_list} ${COLDEFAULT}" echo if [ ${MAGE_UNINSTALL_TIMEOUT} -gt 0 ] then echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo "( Press [CTRL+C] to abort )" echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -n "Waiting ${MAGE_UNINSTALL_TIMEOUT} seconds ..." for ((i=MAGE_UNINSTALL_TIMEOUT; i >= 0; i--)) do echo -ne "${COLRED} ${i}${COLDEFAULT}" sleep 1 done echo echo fi for pkg in ${list} do pcat=$(dep2pcat ${pkg}) pname=$(magename2pname ${pkg}) pver=$(magename2pver ${pkg}) pbuild=$(magename2pbuild ${pkg}) mage_uninstall \ --pcat ${pcat} \ --pname ${pname} \ --pver ${pver} \ --pbuild ${pbuild} \ --count-total ${total_pkgs} \ --count-current ${current_pkg} \ ${src_install} # crlf for better view in VERBOSE mode #if [[ ${VERBOSE} = on ]]; then echo; fi echo done } mage_uninstall() { # local all possible vars of a mage file # to prevent bad issues local PKGNAME local STATE local DESCRIPTION local HOMEPAGE local DEPEND local SDEPEND local PROVIDE local PKGTYPE local preinstall local postinstall local preremove local postremove local pcat local pname local pver local pbuild local magefile local i # very basic getops for i in $* do case $1 in --pcat|-c) shift; pcat="$1" ;; --pname|-n) shift; pname="$1" ;; --pver|-v) shift; pver="$1" ;; --pbuild|-b) shift; pbuild="$1" ;; esac shift done # sanity checks; abort if not given [ -z "${pcat}" ] && die "mage_uninstall() \$pcat not given." [ -z "${pname}" ] && die "mage_uninstall() \$pname not given." [ -z "${pver}" ] && die "mage_uninstall() \$pver not given." [ -z "${pbuild}" ] && die "mage_uninstall() \$pbuild not given." # check needed global vars [ -z "${MAGEDIR}" ] && die "mage_uninstall() \$MAGEDIR not set." [ -z "${INSTALLDB}" ] && die "mage_uninstall() \$INSTALLDB not set." [ -z "${BUILDDIR}" ] && die "mage_uninstall() \$BUILDDIR not set." xtitle "[ (${count_current}/${count_total}) Removing ${pcat}/${pname}-${pver}-${pbuild} ]" echo -ne "${COLBLUE} <<< ${COLDEFAULT}" echo -n "removing: " echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" echo -e "${COLRED}${pname}-${pver}-${pbuild}${COLDEFAULT}" magefile="${INSTALLDB}/${pcat}/${pname}-${pver}-${pbuild}/${pname}-${pver}-${pbuild}.mage" source ${magefile} ## preremove scripts if [ -n "$(typeset -f preremove)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running preremove ... " preremove unset preremove fi # runs uninstall build_douninstall \ --pcat "${pcat}" \ --pname "${pname}" \ --pver "${pver}" \ --pbuild "${pbuild}" ## postremove scripts if [ -n "$(typeset -f postremove)" ] then echo -e " ${COLBLUE}***${COLDEFAULT} running postremove ... " postremove unset postremove fi # removes the database entry remove_database_entry \ --pcat "${pcat}" \ --pname "${pname}" \ --pver "${pver}" \ --pbuild "${pbuild}" \ || die "error in mage_uninstall() running remove_database_entry()." # rebuilds toplevel info node if [[ ${MAGE_INFO_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding top-level info node ... " ${MLIBDIR}/mkinfodir ${MROOT}/usr/share/info \ > ${MROOT}/usr/share/info/dir && \ echo "done." || echo "failure." unset MAGE_INFO_REBUILD fi # rebuilds the enviroment with the content of /etc/env.d if [[ ${MAGE_ENV_REBUILD} = true ]] then echo -ne "${COLBLUE} *** ${COLDEFAULT}" echo -n "rebuilding environment ... " ${MLIBDIR}/env-rebuild.sh > /dev/null && \ echo "done." || echo "failure." unset MAGE_ENV_REBUILD fi echo -ne "${COLBLUE} --- ${COLDEFAULT}" echo -n "package " # echo -ne "${COLBLUE}${pcat}/${COLDEFAULT}" # echo -ne "${COLGREEN}${pname}-${pver}-${pbuild}${COLDEFAULT} " echo "successfully removed." # unset these functions unset -f preinstall unset -f postinstall unset -f preremove unset -f postremove } show_etc_update_mesg() { [ ${MAGE_PROTECT_COUNTER} -eq 0 ] && return 0 echo echo -ne "${COLRED}" echo "Important:" echo -ne ${COLDEFAULT} echo "${MAGE_PROTECT_COUNTER} protected file(s) were installed." echo echo "Please run 'etc-update' to update your configuration files." echo } pkgsearch() { local string="$1" local result local pkg local pcat local pname local magefile local pver local pbuild local state local descriptiom local homepage local i local all_installed local ipver local ipbuild local latest_available # only names no versions result="$(find ${MAGEDIR} -mindepth 2 -maxdepth 2 -type d -name '*'${string}'*'| sed '/profiles/d' | sed '/includes/d')" #result="$(find ${MAGEDIR} -type f -name '*'${string}'*'.mage | sort)" # nothing found [[ -z ${result} ]] && die "No package found containing '${string}' in the name." for pkg in ${result} do # dirty, but does the job pcat="$(magename2pcat ${pkg}/foo)" pname="$(magename2pname ${pkg}-foo-foo)" # get highest version available magefile=$(get_highest_magefile ${pcat} ${pname}) if [[ ! -z ${magefile} ]] then # now get all needed infos to print a nice output pver="$(magename2pver ${magefile})" pbuild="$(magename2pbuild ${magefile})" state="$(get_value_from_magefile STATE ${magefile})" description="$(get_value_from_magefile DESCRIPTION ${magefile})" homepage="$(get_value_from_magefile HOMEPAGE ${magefile})" # all installed for i in $(get_uninstall_candidates --pname ${pname} --pcat ${pcat}) do ipver="$(magename2pver ${i})" ipbuild="$(magename2pbuild ${i})" if [[ -z ${all_installed} ]] then all_installed="${ipver}-${ipbuild}" else all_installed="${all_installed} ${ipver}-${ipbuild}" fi done [[ -z ${all_installed} ]] && all_installed="none" case ${state} in stable) state=${COLGREEN}"[s] ";; testing) state=${COLYELLOW}"[t] ";; unstable) state=${COLRED}"[u] ";; old) state=${COLGRAY}"[o] ";; esac latest_available="${pver}-${pbuild}" else # package is masked state="${COLRED}[m] " latest_available="${COLRED}masked for this distribution.${COLDEFAULT}" fi echo -e "${state}${pcat}/${pname}"${COLDEFAULT} echo -e " Latest available: ${latest_available}" echo " Installed versions: ${all_installed}" echo " Description: ${description}" echo " Homepage: ${homepage}" echo unset pcat unset pname unset magefile unset pver unset pbuild unset state unset descriptiom unset homepage unset all_installed unset ipver unset ipbuild done } export_inherits() { local include="$1" shift while [ "$1" ] do local functions="$1" # sanity checks [ -z "${include}" ] && die "export_inherits(): \$include not given." [ -z "${functions}" ] && die "export_inherits(): \$functions not given." eval "${functions}() { ${include}_${functions} ; }" # debug [[ ${MAGEDEBUG} = on ]] && typeset -f "${functions}" shift done } mlibdir() { local libdir=lib [[ ${ARCH} = x86_64 ]] && libdir=lib64 echo "${libdir}" } ## blacklisted ${magefile} blacklisted() { [[ -z ${MAGE_DISTRIBUTION} ]] && local MAGE_DISTRIBUTION=stable # compat [[ ${USE_UNSTABLE} = true ]] && local MAGE_DISTRIBUTION=unstable [[ ${USE_TESTING} = true ]] && local MAGE_DISTRIBUTION=testing local EXCLUDED="${MROOT}/etc/mage-profile/package.blacklist-${ARCH}-${MAGE_DISTRIBUTION}" # return 0 if the list not exist; nothin is masked [[ ! -f ${EXCLUDED} ]] && return 0 local MAGEFILE="$1" local PCAT="$(magename2pcat ${MAGEFILE})" local PNAME="$(magename2pname ${MAGEFILE})" local PVER="$(magename2pver ${MAGEFILE})" local PBUILD="$(magename2pbuild ${MAGEFILE})" local EXPCAT EXPNAME EXPVER EXPBUILD while read EXPCAT EXPNAME EXPVER EXPBUILD do # ignore spaces and comments case "${EXPCAT}" in \#*|"") continue ;; esac # exclude full pver if [[ -n ${PCAT} ]] && [[ -n ${PNAME} ]] && [[ -n ${EXPCAT} ]] && [[ -n ${EXPNAME} ]] && [[ -n ${PVER} ]] && [[ -n ${PBUILD} ]] && [[ -n ${EXPVER} ]] && [[ -n ${EXPBUILD} ]] then [[ ${EXPCAT}/${EXPNAME}-${EXPVER}-${EXPBUILD} = ${PCAT}/${PNAME}-${PVER}-${PBUILD} ]] && return 1 fi # exclude pcat/pname only if [[ -n ${PCAT} ]] && [[ -n ${PNAME} ]] && [[ -n ${EXPCAT} ]] && [[ -n ${EXPNAME} ]] && [[ -z ${EXPVER} ]] && [[ -z ${EXPBUILD} ]] then [[ ${EXPCAT}/${EXPNAME} = ${PCAT}/${PNAME} ]] && return 1 fi done << EOF $( cat ${EXCLUDED}; echo) EOF return 0 }