#!/bin/sh cfg_common_ver_=2.2 # set -x ############################################################################## # Copyright (C) cfg.common, C. Ostheimer and , licensed under # GNU General Public License version 2 (GPL v2.0) # # 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; spblinux.de/fbox.new/gpl-2.0.txt # # Version: $cfg_common_ver_ 2.2 # Date: 23.12.20 # 09.03.2008 Enhanced ovrly to also allow files instead of dirs # 12.02.2008 Added function for cfg.common version control # 27.04.2007 Adjusted instdir-function to also allow "/var/media/ftp" as USB-Mount point # by dynamic and spblinux, 2007-01 # cfg.common # - helper functions to control addons # - to be sourced by cfg_asterisk and other addon scripts # - all variables used(*) by this script have a trailing underline, e.g. i_ # *) they may get changed, overwritten, deleted #################################################################### # Changes: # - new 2007-12 : root install using mount -o bind and softlinks; # helper functions: cfgctl, ovrly # - cp... made parm1_ (cp options) optional # - cprs use -R (-r not supported with old firmware) # - cprs added optional parameter(s) to exclude directories/files # - ln... always (re)create links (existing links might point to wrong target) # - new internal function shift_parms_ # - new (not only) internal functions get_inst_basedir_, get_missing_file_ # - added function lnsf2: like lnsf but create multiple links to same file # - added function lndfe: like lndf but added parameters exclude dir(s) # - added function lndf2: like lndf but added parameter chroot_dir # (usage: lookup files in /chroot_dir/source_dir during installation # but access files at /source_dir when running in chroot environment) # - added wgety (=wgetx, but does not exit if file cannot be downloaded) # - added _fct functions modext, svrsub, path_abs # Suggestions of things to be added: # - further functions potentially required for other installations # - verbose flag with additional output for _fct functions # - other common functions e.g. ramdisk , errorexit etc. #################################################################### cmp_version() # check if $2 >= $1, with $1 Version-Required and $2 Cur_Version { major_req_=${1%\.*} major_cur_=${2%\.*} [ $major_cur_ -gt $major_req_ ] && return 0 [ $major_cur_ -lt $major_req_ ] && return 1 if [ $major_cur_ -eq $major_req_ ];then [ "$major_req_" = "$1" ] && return 0 [ "$major_cur_" = "$2" ] && return 1 minor_req_=${1#*\.} minor_cur_=${2#*\.} req_digit_=${minor_req_%${minor_req_#?}} cur_digit_=${minor_cur_%${minor_cur_#?}} while [ "$req_digit_" != "" ] do [ "$cur_digit_" = "" ] && return 1 [ $cur_digit_ -gt $req_digit_ ] && return 0 [ $cur_digit_ -lt $req_digit_ ] && return 1 minor_req_=${minor_req_#?} minor_cur_=${minor_cur_#?} req_digit_=${minor_req_%${minor_req_#?}} cur_digit_=${minor_cur_%${minor_cur_#?}} done return 0 fi return 1 } if [ "$1" = "cmp_version" ];then if cmp_version $2 $cfg_common_ver_;then echo "`basename $0`: current v$cfg_common_ver_ >= required v$2 -> OK";exit else echo "`basename $0`: current v$cfg_common_ver_ < required v$2 -> NOK, need to upgrade";exit fi fi errorexit() { echo -e "$@" exit 1 } ######################################################################## # internal function: shift_parms_ # - remove parm1_ and copy # parm1_=parm2_, parm2_=parm3_ ... parm<$i_-1>_=parm<$i_>_ # unset parm<$i_>_ # let i_-=1 # purpose: allow optional parameters ######################################################################## shift_parms_() { if [ $i_ -ge 1 ]; then j_=1 k_=2 while [ $k_ -le $i_ ]; do eval parm${j_}_=`eval echo \\$parm${k_}_` let j_+=1 let k_+=1 done eval unset parm${i_}_ let i_-=1 fi } ######################################################################## # internal function: mkdir_rcrsv_ [ ] # - create all levels of required directory structure provided in # - consider to be relative to if parm is set # - if is omitted, is assumed to be an absolute directory path ######################################################################## mkdir_rcrsv_() { if [ $# -gt 1 ];then create_dir_=$1 parms_=$2 [ -d $create_dir_ ] || errorexit "$funct_: Base directory $create_dir_ does not exist." else create_dir_="" parms_=$1 fi for d_ in `echo $parms_ | sed "s/\// /g"`;do create_dir_=$create_dir_/$d_ if ! [ -d $create_dir_ ];then mkdir $create_dir_ || errorexit "$funct_: No RW File System ($create_dir_)" fi done } ######################################################################## # internal function: get_inst_basedir_ # - returns the installation base directory D to stdout using /var/${addon}_usb # (the symlink /var/${addon}_usb points to D/addons/$addon) ######################################################################## get_inst_basedir_() { if [ -L /var/${addon}_usb ]; then ls -l /var/${addon}_usb |sed "s/.* \([^ ]*\)\/addons\/$addon$/\1/" fi } ######################################################################## # internal function: get_inst_realdir_ [installation_directory] # - returns the real installation base directory D_real # (D_real is the real mountpoint of D; (D=`get_inst_basedir_`); # either D == D_real or D is a symlink or a relative path pointing to D_real) ######################################################################## get_inst_realdir_() { if [ $# -eq 1 ]; then dir_tmp_=$1 else dir_tmp_=`get_inst_basedir_` fi if [ -d "$dir_tmp_" ]; then if ! [ -L $dir_tmp_ ] && [ $dir_tmp_ != ${dir_tmp_#/} ] && \ ! echo $dir_tmp_ |grep -q "\.\." ; then echo $dir_tmp_ else mkdir $dir_tmp_/testfs.$PPID || errorexit "function get_inst_realdir: error: $dir_tmp_ is not writable" mount -t tmpfs testfs $dir_tmp_/testfs.$PPID || errorexit "function get_inst_realdir: error: cannot mount tmpfs on $dir_tmp_" mount |grep "testfs.$PPID" |sed "s/^testfs on \([^ ]*\)\/testfs.$PPID type tmpfs.*$/\1/" umount $dir_tmp_/testfs.$PPID || errorexit "function get_inst_realdir" rm -r $dir_tmp_/testfs.$PPID || errorexit "function get_inst_realdir" fi fi unset dir_tmp_ } ######################################################################## # internal function: get_missing_file_ [-x | -X | -s | -i] [path/]file_name [args...] # - checks if file f is in /var: if yes, return true and make executable if -x is given # - then tries to: copy f to /var | execute f with args| source f | insmod f # - first, if given, from path given with file_name, # and from directory where $0 is called from # - second, if /var/${addon}_usb exists, from /a/b/c/.. # if ${addon}_usb points to /a/b/c # - third from $server$svrsub # - fourth from $server # return value = true if: found |result of execution|result of insmod ######################################################################## get_missing_file_() { unset is_exec_ do_exec_ do_source_ do_insmod_ while [ $# -gt 1 -a x${1#-} != x$1 ]; do case $1 in -x) is_exec_=1;; -X) do_exec_=1;; -s) do_source_=1;; -i) do_insmod_=1;; esac shift done fb_=${1##*/} fm_=/var/$fb_ while ! [ -f $fm_ ]; do [ -f $1 ] && fm_=$1 && break [ -f ${0%/*}/$fb_ ] && fm_=${0%/*}/$fb_ && break d_=`get_inst_basedir_` [ "$d_" ] && [ -f $d_/addons/$fb_ ] && fm_=$d_/addons/$fb_ && break wget $server$svrsub/$fb_ -O $fm_ && break wget $server/$fb_ -O $fm_ unset fm_ break done if [ "$fm_" ]; then if [ "$do_insmod_" ]; then if [ "$verbose" ]; then insmod $fm_; else insmod $fm_ 2>/dev/null; fi elif [ "$do_source_" ]; then . $fm_ elif [ "$do_exec_" -a $# -gt 1 ]; then chmod +x $fm_ shift $fm_ $@ else [ -f /var/$fb_ ] || cp $fm_ /var/$fb_ [ "$is_exec_" ] && chmod +x /var/$fb_ # create return value [ -f /var/$fb_ ] fi else # create return value [ "$fm_" ] fi } ######################################################### # usage: _fct funct_name@parm1[:parm2][:parm3]...[:parm{n}] ######################################################### _fct() { # Determine function funct_=${1%%@*} case $funct_ in #non verbose functions (which return their value by stdout) must be listed here modext | svrsub | path_abs) ;; *) [ $verbose ] && echo "Executing: _fct $1" esac i_=0 # Determine parameters for function and store in variables parm1_, parm2_, parm3_, ... parm{n}_ args_=`echo \${1#*@} | sed "s/:/ /g"` for parm_ in $args_;do let i_+=1 eval parm${i_}_="$parm_" done case $funct_ in ######################################################### instdir) # instdir@/var/media/ftp|::varname_install_root_dir:varname_fs_type # Determine if "/var/media/ftp" is provided # or assume otherwise. # Return install_root_dir and fs-type information stored in variable names provided. # Also confirm that FS is RW and create on determined . Errorexit if it is nor a RW Filesystem. # PARMS: # /var/media/ftp: absolute path to default FBF USB moint-point , where attached and mounted USB-drives are expected ( if usb-device is to be determined under /var/media/ftp/* ) # : absolute directory name, where $addon is to be installed, in case end-user has provided fully qialified directory name for installation. # : addons/$addon package name, e.g. addons/asterisk, addons/dropbear etc. # varname_install_root_dir: name of variable, where fully specified installation directory will be returned in # varname_fs_type: name of variable, where fs-type of fully specified installation directory will be returned in [ $i_ -eq 4 ] || errorexit "$funct_: Insufficient number of parameters" if [ $parm1_ = "/var/media/ftp" -o $parm1_ = "/var/media/ftp/" ];then unset path_ for path_ in `mount | grep "on $parm1_" | sed "s,^.* \(.*\) \(.*\) \(.*\) \(.*\),\1,"`;do [ -d $path_/$parm2_ ] && break done [ -d "$path_" ] || errorexit "$funct_: No attached and mounted usb-device found under \"/var/media/ftp/\"" else [ -d $parm1_ ] || errorexit "$funct_: Installation path provided \"$parm1_\" does not exist!" path_=$parm1_ fi det_mnt_=$path_ while [ $det_mnt_ ];do # If installation path is references by a Symbolinc Link, then determine the realpath if [ -L $det_mnt_ ];then # temporarily use det_mnt_ as buffer variable det_mnt_="`ls -l $det_mnt_`" # set det_mnt_ to realpath of symbolic link ( basically the path the symbolinc link is pointing to) det_mnt_=${det_mnt_##* -> }; fi # Determine FS-Type if mount-point located if mnt_pnt_=`mount | grep "on $det_mnt_ "`;then # Errorexit if Installation path provided is a "read only (RO)" File Sysren echo $mnt_pnt_ | sed "s,^.* \(.*\) \(.*\) \(.*\) \(.*\),\4," | grep -q "[(,]ro[,)]" && errorexit "$funct_: Installation path \"$path_\" is on a Read Only FS!" # Store FS-Type of mount point located in variable name provided by $parm4_ eval $parm4_=`echo $mnt_pnt_ | sed "s,^.* \(.*\) \(.*\) \(.*\) \(.*\),\3,"` # Store install root dir information in variable name provided by $parm3_ eval $parm3_=$path_ mkdir_rcrsv_ $path_ $parm2_ break; fi # go up one level in directory hierarchy det_mnt_=${det_mnt_%/*} done ;; ######################################################### cfgctl) # cfgctl@:|| # Controls mode of cfg_xxxx application status ( enabled / disabled ) # PARMS: # : Name of application script invoking this function # : Command to check application status and store result in variable "varname" # : Re-activates application and allows normal start / stop / install # : Disables application and prevents start / stop / [usb_]install|remove ######################################################### unset j_ [ $i_ -ge 1 ] && case $parm2_ in check ) [ $i_ -eq 3 ] && j_=1;; enable | disable ) [ $i_ -eq 2 ] && j_=1;; * ) errorexit "$funct_: Wrong parameter \"$parm1_\" used in function";; esac [ "$j_" ] || errorexit "$funct_: Wrong number of parameters" ctrl_file_=/var/flash/debug.cfg ctrl_file_tmp_=/var/`basename $ctrl_file_`.tmp ctrl_pattern_="###DON'T REMOVE. PUTS FOLLOWING APP INTO MAINT-MODE: " if grep -q "${ctrl_pattern_}${parm1_}" $ctrl_file_ 2>/dev/null; then case $parm2_ in check ) eval $parm3_=disabled;; enable ) grep -v "${ctrl_pattern_}${parm1_}" $ctrl_file_ >$ctrl_file_tmp_ && \ cat $ctrl_file_tmp_ >$ctrl_file_ echo "********************************************************************" echo "- ATTENTION -" echo "$parm1_: has been activated and put to normal operation mode again." echo "Application will allow to start and install again!" echo "********************************************************************" ;; esac else case $parm2_ in check ) eval $parm3_=enabled;; disable ) if cat $0 >/dev/null; then # after factory reset /var/flash/debug.cfg does not exist; create it (but make sure that cat and /dev/null are working) cat $ctrl_file_ >/dev/null 2>&1 || echo "#" >$ctrl_file_ fi cat $ctrl_file_ >$ctrl_file_tmp_ && \ echo -e "\n${ctrl_pattern_}${parm1_} \c" >> $ctrl_file_tmp_ && \ cat $ctrl_file_tmp_ >$ctrl_file_ echo "********************************************************************" echo "- ATTENTION -" echo "$parm1_ has been deactivated and put into system maintenance mode now!" echo "It will not allow to start or install until you enable via" echo "\"$parm1_ enable\" again" echo "********************************************************************" ;; esac fi ;; ######################################################### ovrly) # ovrly@RO|RW:[:][:][: into /var/_RW_/_ and softlinks files and directories from # PARMS: # : If set to "RO" existing files in will be kept and not replaced by another softlink # If set to "RW" existing files in will be replaced by subsequent files and directories # : Read Only dir that will be overlayed and look as being Read Write # : Absolute reference to file or directory which will be overlayed in / onto # Dependencies / Expected external variables: # ro_source_ : variable pointing to path where "/" has been mounted to ( via mount -o bind ) # rw_target_ : variable pointing to path where RW strcuture will be recreated # ovr_init_ : to be set to "true" indicating that ovradm:bind has run successfully ######################################################### # Attention: # Even though it is possible to change files in /lib /bin and /sbin etc. it is recommended not to do so, # unless you really know what you do and why you do it! # Be aware that directory cannot be unmounted while other processes are accessing files on it. # A full uninstall will therefore only be possible after cfg_xxx applications have been put to "disable" mode # ( maintenance mode ) and the system has been rebooted. ######################################################### [ $i_ -ge 2 ] || errorexit "$funct_: Insufficient number of parameters" if ! [ "$ovr_init_" ];then ro_source_=/var/_RO_ rw_target_=/var/_RW_ if ! `mount | grep "on $ro_source_ " | sed "s/^\([^ ]*\) .*/\1/" | grep -q /dev/root`;then [ -d $ro_source_ ] || mkdir_rcrsv_ $ro_source_ mount -o bind / $ro_source_ || errorexit "$funct_: Failed to mount / to $ro_source_" fi [ -d $rw_target_ ] || mkdir_rcrsv_ $rw_target_ ovr_init_=1 fi let x_=2 new_sftlnks_=0 mounted_=false ovr_dir_=`echo $parm2_ | sed "s/\//_/g"` #### Skip the respective root directory if it is already mounted by another cfg_xxxx script #### mount | grep "on $parm2_ " | sed "s/^\([^ ]*\) .*/\1/" | grep -q ramfs && let x_+=1 && mounted_=true $mounted_ || mkdir_rcrsv_ $rw_target_/$ovr_dir_ save_pwd_=`pwd` cd $rw_target_/$ovr_dir_ while [ $x_ -le $i_ ] do dir_=`eval echo \\$parm${x_}_` #### Option -A does not list implied "." and ".." directories #### if [ -d $dir_ ]; then files_=`ls -A $dir_` else files_=`basename $dir_` dir_=${dir_%/*} fi for file_ in $files_;do #### Check if file already exists from previous directory layers #### #### Check if files from previous folders should be overwritten #### if ! [ -f $rw_target_/$ovr_dir_/$file_ -a "$parm1_" = "RO" ];then [ -f $rw_target_/$ovr_dir_/$file_ ] && rm $rw_target_/$ovr_dir_/$file_ #### If file is a softlink then create new softlink directly to target ( no need for softlink -> softlink ) #### if [ -L $dir_/$file_ ];then soft_linked_to_=`ls -l $dir_/$file_` soft_linked_to_=${soft_linked_to_#*-> } case $dir_ in /etc* | /usr* | /bin* | /lib* | /sbin* ) ln -s $soft_linked_to_ $file_ ;; #### Softlinks to non root directories will be replaced by absoulte paths instead #### * ) ln -s $dir_/$file_ ;; esac else let new_sftlnks_+=1 case $dir_ in /etc* | /usr* | /bin* | /lib* | /sbin* ) ln -s $ro_source_$dir_/$file_ ;; * ) ln -s $dir_/$file_ ;; esac fi else [ $verbose ] && echo "Warning: _fct $1: $parm2_/$file_ NOT REPLACED WITH $dir_/$file_" fi done let x_+=1 done $mounted_ || mount --bind $rw_target_/$ovr_dir_ $parm2_ [ $verbose ] && echo "Informat.: _fct $1: $new_sftlnks_ softlinks added to $parm2_" cd $save_pwd_ ;; ######################################################### mkdr) # mkdr@:[:][:]...[:] # Create directory path ... relative to # PARMS: # : absolute path to RW filesystem # : drectory paths to be created relative to [ $i_ -ge 2 ] || errorexit "$funct_: Insufficient number of parameters" let x_=2 while [ $x_ -le $i_ ] do mkdir_rcrsv_ $parm1_ `eval echo \\$parm${x_}_` let x_+=1 done ;; ######################################################### cpnr) # cpnr@[copy_options:]:[:file1][:file2]...[:file{n}] # Copy file1 ... file{n} ( or * if no files specified ) from to . File attributes will be preserved. # PARMS: # : options for cp command with leading "-" # : absolute path to copy from # : absolute target path to copy files to. will be created if not existing. # file{n}: optional file names to be copied. Copy "*" ( all ) assumed if no file name(s) specified unset options_ if [ $i_ -ge 3 -a ! -d "$parm1_" ]; then # assume $parm1_ contains options options_=$parm1_ shift_parms_ fi [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number ($i_) of parameters into function: $funct_" ! [ -d $parm2_ ] && mkdir_rcrsv_ $parm2_ if [ $i_ -gt 2 ];then let x_=3 while [ $x_ -le $i_ ] do cp $options_ $parm1_/`eval echo \\$parm${x_}_` $parm2_ let x_+=1 done else # copy all files unless directory is empty for f_ in $parm1_/*; do [ "$f_" = "$parm1_/*" ] && break cp $options_ $parm1_/* $parm2_ break done fi ;; ######################################################### cprs) # cprs@[copy_options:]:[:exclude_dir[:exclude_dir2[:...]]] # Copy recursively to . File attributes will be preserved. # PARMS: # : options for cp command with leading "-" # : absolute path to copy from # : absolute target path to copy files to. will be created if not existing. unset options_ if [ $i_ -ge 3 -a ! -d "$parm1_" ]; then # assume $parm1_ contains options options_=$parm1_ shift_parms_ fi [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number ($i_) of parameters into function: $funct_" [ -d $parm2_ ] || mkdir_rcrsv_ $parm2_ if [ $i_ -eq 2 ]; then for f_ in $parm1_/*; do [ "$f_" = "$parm1_/*" ] && break cp -R $options_ $parm1_/* $parm2_ break done else for f_ in $parm1_/*; do [ "$f_" = "$parm1_/*" ] && break unset is_exclude_dir_ let x_=3 while [ $x_ -le $i_ -a -z "$is_exclude_dir" ]; do exclude_dir_=`eval echo \\$parm${x_}_` [ `basename $f_` = $exclude_dir_ ] && is_exclude_dir_=1 let x_+=1 done [ "$is_exclude_dir_" ] && continue cp -R $options_ $f_ $parm2_ done fi ;; ######################################################### cpdf) # cpdf@[copy_options:]:[:exclude_dir[:exclude_dir2[:...]]] # Copy *.default from to . ".default" extension is omitted in . Existing files in WILL BE KEPT / NOT BE OVERWRITTEN. # PARMS: # : options for cp command with leading "-" # : absolute path to copy from # : absolute target path to copy files to. will be created if not existing. unset options_ if [ $i_ -eq 3 -a ! -d "$parm1_" ]; then # assume $parm1_ contains options options_=$parm1_ shift_parms_ fi [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number ($i_) of parameters into function: $funct_" ! [ -d $parm2_ ] && mkdir_rcrsv_ $parm2_ for f_ in $parm1_/*.default; do [ "$f_" = "$parm1_/*.default" ] && break f_=${f_##*/} unset is_exclude_dir_ let x_=3 while [ $x_ -le $i_ -a -z "$is_exclude_dir" ]; do exclude_dir_=`eval echo \\$parm${x_}_` [ $f_ = $exclude_dir_ ] && is_exclude_dir_=1 let x_+=1 done [ "$is_exclude_dir_" ] && continue if [ -f $parm2_/${f_%.default} ];then echo "not overwriting $parm2_/${f_%.default}" else cp $options_ $parm1_/$f_ $parm2_/${f_%.default} fi done ;; ######################################################### cpnL) # cpnL@[copy_options:]:[:exclude_dir[:exclude_dir2[:...]]] # Copy * from to . Ignore if file is SYMBOLIC LINK! # PARMS: # : options for cp command with leading "-" # : absolute path to copy from # : absolute target path to copy files to. will be created if not existing. unset options_ if [ $i_ -eq 3 -a ! -d "$parm1_" ]; then # assume $parm1_ contains options options_=$parm1_ shift_parms_ fi [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number ($i_) of parameters into function: $funct_" ! [ -d $parm2_ ] && mkdir_rcrsv_ $parm2_ for f_ in $parm1_/*;do [ "$f_" = "$parm1_/*" ] && break unset is_exclude_dir_ let x_=3 while [ $x_ -le $i_ -a -z "$is_exclude_dir" ]; do exclude_dir_=`eval echo \\$parm${x_}_` [ ${f_##*/} = $exclude_dir_ ] && is_exclude_dir_=1 let x_+=1 done [ "$is_exclude_dir_" ] && continue [ -L $f_ ] || cp $options_ $f_ $parm2_/${f_##*/} done ;; ######################################################### lnsf) # lnsf@<[target_dir/]link_name|:[:]...[:] # Create a link named link_name in current (or target) directory to # OR create one ore more symbolic links to in # (warning: existing directories will be removed and replaced by symbolic links) # PARMS: # : name of symbolic link to be created in current (or target) dir ( $PWD ) # : target path where symbolic links to will be created # : relative (or absolute) directory or file path to be linked in [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" let x_=2 while [ $x_ -le $i_ ] do softlink_=`eval echo \\$parm${x_}_` [ -d $parm1_/`basename $softlink_` ] && rm -r $parm1_/`basename $softlink_` ln -sf $softlink_ $parm1_ let x_+=1 done ;; ######################################################### lnsf2) # lnsf2@:[:]...[:]: # Create one ore more symbolic links to in # (warning: existing directories will be removed and replaced by symbolic links) # PARMS: # : name(s) (without path) of symbolic link(s) to be created in target dir # : target path where symbolic links to will be created # : relative (or absolute) directory or file path to be linked in [ $i_ -ge 3 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" softlinkpath_=`eval echo \\$parm${i_}_` let x_=2 while [ $x_ -lt $i_ ] do softlinkname_=`eval echo \\$parm${x_}_` [ -d $parm1_/$softlinkname_ ] && rm -r $parm1_/$softlinkname_ ln -sf $softlinkpath_ $parm1_/$softlinkname_ let x_+=1 done ;; ######################################################### lndf) # Create forced softlink to Files/Dirs to $parm2_/$parmX if no similar items exist in $parm1_ already [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" if [ $i_ -gt 2 ];then let x_=3 while [ $x_ -le $i_ ] do softlink_=`eval echo \\$parm${x_}_` for ro_item_ in $parm2_/$softlink_;do if [ -f $parm1_/$ro_item_ -o -d $parm1_/$ro_item_ ];then echo "File exists in RW space. Not linking $parm2_/$ro_item_." else [ -L $parm1_/$ro_item_ ] || ln -sf $parm2_/$ro_item_ $parm1_ fi done let x_+=1 done else for ro_item_ in $parm2_/*;do [ "$ro_item_" = "$parm2_/*" ] && break if [ -f $parm1_/${ro_item_##*/} -o -d $parm1_/${ro_item_##*/} ]; then echo "File {ro_item_##*/} exists in RW space. Not linking $ro_item_." else ln -sf $ro_item_ $parm1_ fi done fi ;; ######################################################### lndfe) # Create forced softlink to Files/Dirs to $parm2_/$parmX if no similar items exist in $parm1_ already # parm1: directory into which symlinks are written # parm2: contents of this directory are the targets of the symlinks # optional: parm3, parm4 ... directories (or files) which have to be excluded [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" for ro_item_ in $parm2_/*;do [ "$ro_item_" = "$parm2_/*" ] && break unset is_exclude_dir_ if [ $i_ -gt 2 ]; then let x_=3 while [ $x_ -le $i_ -a -z "$is_exclude_dir" ]; do exclude_dir_=`eval echo \\$parm${x_}_` [ `basename $ro_item_` = $exclude_dir_ ] && is_exclude_dir_=1 let x_+=1 done fi [ "$is_exclude_dir_" ] && continue if [ -f $parm1_/${ro_item_##*/} -o -d $parm1_/${ro_item_##*/} ]; then echo "File {ro_item_##*/} exists in RW space. Not linking $ro_item_." else ln -sf $ro_item_ $parm1_ fi done ;; ######################################################### lndf2) # lndf2@:: # For files in / create forced symbolic links # pointing to /f (if f is a file in /) # All links are created in target dir; do not overwrite existing files # [ $i_ -eq 3 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" for ro_item_ in $parm2_/$parm3_/*;do [ "$ro_item_" = "$parm2_/$parm3_/*" ] && break if [ -f $parm1_/${ro_item_##*/} -o -d $parm1_/${ro_item_##*/} ]; then echo "File {ro_item_##*/} exists in RW space. Not linking to $ro_item_." else ln -sf $parm3_/${ro_item_##*/} $parm1_ fi done ;; ######################################################### wgetx | wgety) # Download $parm${n}_ files from source $parm2_ to directory $parm3_, if files not already in $parm3_ # wgetx@http|ftp:[//][user[:password]@]www.serverfrom.com:/target/dir:file1:[file2]:[file{n}] # wgety: like wgetx but continue in case of errors; just return false then. [ $i_ -ge 4 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" [ $parm1_ = "http" -o $parm1_ = "ftp" ] || errorexit "$funct_: Unknown protocol \"$parm1_\" used for wget function." # allow ftp://user:pw@server (only if passwort does not contain ":" or "@") if [ $parm3_ != ${parm3_%@*} ]; then parm3_=$parm2_:$parm3_ parm2_=$parm1_ shift_parms_ fi if [ $funct_ = wgety ]; then result_=0 else unset result_ fi let x_=4 while [ $x_ -le $i_ ] do file_=`eval echo \\$parm${x_}_` if [ -b $parm3_ ]; then # target is block device (e.g. ramdisk) # trim leading "//" if $parm2_ is in format "//www.spblinux.de" if ! wget $parm1_://${parm2_##*//}/$file_ -O $parm3_; then [ "$result_" ] || errorexit "$funct_: Couldn't download \"${parm2_##*//}/$file_\"" result_=1 fi else if ! [ -f $parm3_/$file_ ];then # trim leading "//" if $parm2_ is in format "//www.spblinux.de" if ! wget $parm1_://${parm2_##*//}/$file_ -O $parm3_/$file_; then [ "$result_" ] || errorexit "$funct_: Couldn't download \"${parm2_##*//}/$file_\"" result_=1 fi fi fi let x_+=1 done # create return value (true or false) for wgety [ "$result_" ] && [ $result_ -eq 0 ] ;; ######################################################### rdsk) # ramdisk helper functions # usage: _fct rdsk@ # usage: _fct rdsk@:ramdisk_device # usage: _fct rdsk@new:varname_ramdisk_device[:dir_with_freeramdisk] # usage: _fct rdsk@get-device:varname_ramdisk_device:mount_directory # start/stop: load/unload ramdisk kernel module # new: return a free (unmounted) ramdisk in variable given by $parm2_ # get_device: return at $parm3_ mounted ramdisk in variable given by $parm2_ # in_use: return true if ramdisk given by $parm2_ (absolute path!) is mounted # free: run freeramdisk for ramdisk given in $parm2_ # unset j_ [ $i_ -ge 1 ] && case $parm1_ in start) [ $i_ -le 2 ] && j_=1;; stop) [ $i_ -eq 1 ] && j_=1;; new | free) [ $i_ -eq 2 -o $i_ -eq 3 ] && j_=1;; in_use) [ $i_ -eq 2 ] && j_=1;; get_device) [ $i_ -eq 3 ] && j_=1;; esac [ "$j_" ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" result_=0 case $parm1_ in start) if uname -r |grep -q "^2.6"; then modext_=ko; else modext_=o; fi f_=rd.$modext_ while [ 1 ]; do lsmod |grep -q "^${f_%%.*} " && break [ -d "$parm2_" ] && f_=${parm2_%/}/$f_ get_missing_file_ -i $f_ && break errorexit "$funct_: failed to load ramdisk kernel module" done ;; stop) if [ "$verbose" ]; then rmmod rd; else rmmod rd 2>/dev/null; fi result_=$? [ $result_ -eq 0 ] || echo "warning ($funct_ $parm1_): failed to unload module rd (other mounted ramdisks?)" ;; get_device) ramdev_=`mount |grep "on $parm3_ " |sed "s/^\([^ ]*\) .*/\1/"` eval $parm2_=$ramdev_ [ -b "$ramdev_" ] || result_=$? ;; in_use) ! [ -b "$parm2_" ] && echo "warning ($funct_ $parm1_): blockdevice \"$parm2_\" does not exist" && break mount |grep -q "^$parm2_ " || result_=$? ;; new | free) if [ $parm1_ = free ]; then ramdev_=$parm2_ else for j_ in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 none; do mount |sed "s@^\([^ ]\+\).*@\1@" |grep -q "^/[dv][ea][vr]/r[da][/m]$j_" && continue break done [ $j_ = none ] && errorexit "error: no free ramdisk found" [ -b ram$j_ ] || mknod ram$j_ b 1 $j_ ramdev_=/var/ram$j_ eval $parm2_=/var/ram$j_ fi f_=freeramdisk [ -d "$parm3_" ] && f_=${parm3_%/}/$f_ while [ 1 ]; do ! [ -b "$ramdev_" ] && echo "warning ($funct_ $parm1_): blockdevice \"$ramdev_\" does not exist" && break get_missing_file_ -X $f_ $ramdev_ && break echo "warning ($funct_ $parm1_): failed to free $ramdev_" break done result_=$? ;; esac # create return value (true or false) [ "$result_" ] && [ $result_ -eq 0 ] ;; ######################################################### mntif) # mount $parm${n-1} to parm${n} using optional mount flags defined in $parm${n-2}, $parm${n-3}, ... [ $i_ -ge 2 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" [ -d `eval echo \\$parm${i_}_` ] || mkdir_rcrsv_ `eval echo \\$parm${i_}_` mount | grep -q "on `eval echo \\$parm${i_}_`" || mount $args_ [ $? -eq 0 ] || errorexit "$funct_: Failed to mount `eval echo \\$parm${i_}_`" ;; fallback) # called if lzma mount of squashfs ramdisk fails ($parm1_=[path]sqf_file) # - if sqf_file is given with path, rename sqf_file to *.lmza if [ $modext = o -a -z "$svr24" ]; then for f_ in $parm1_ $parm2_; do if [ -f "$f_" ]; then if [ -f "$f_.lzma" ]; then rm $f_; else mv $f_ $f_.lzma; fi [ -f "$f_" ] && errorexit "error: cannot remove unmountable sqf file $f_" fi done echo "warning: mount (or download) failure. - Trying fallback to zlib 16kB compression" echo "(if zlib install is successful, e.g. pre 2006 firmware, you should use" echo " ${0##*/} -z install (zlib) or ${0##*/} -Z install (zlib 16kb blocksize))" echo echo "Restarting installation with ${0##*/} -Z install" exec $0 -Z install else errorexit "error: failed to download or to mount $parm1_" fi ;; modext) # has to be listed as non verbose at the beginning of _fct() # returns "ko" (linux 2.6) or "o" (linux 2.4) str_="o" uname -r |grep -q "^2.6" && str_="ko" echo "$str_" unset str_ ;; svrsub) # has to be listed as non verbose at the beginning of _fct() # returns the sub directory used for firmware version specific files # (which is user defined or defaults to /24, /26, /26-ar7) if uname -r |grep -q "^2.6"; then str_="/26" [ "$svr26" ] && str_="${svr26%/}" uname -r |grep "^2\.6" |grep -q "ar7$" && str_=${str_}-ar7 uname -r |grep "^2\.6" |grep -q "\.19" && str_=${str_}-ur8 else str_="/24" [ "$svr24" ] && str_="${svr24%/}" fi echo "/${str_#/}" unset str_ ;; path_abs) # has to be listed as non verbose at the beginning of _fct() # usage: path_abs@filename # returns absolute path to file given by filename # (without trailing slash and without filename) [ $i_ -eq 1 ] || errorexit "$funct_: Incorrect number of parameters into function: $funct_" if [ "${parm1_%%/*}" = "" ];then # $parm1_ is starting with "/" ( absolute path ) str_=${parm1_%/*} else if [ "${parm1_%%/*}" = "." ];then # $parm1_ is starting with "./" ( relative path to $PWD) str_=$PWD/${0#./*} str_=${str_%/*} else # $parm1_ is neither starting with "./" nor with "/" ( relative path to $PWD ) str_=$PWD/${parm1_%/*} fi fi echo "$str_" unset str_ ;; *) errorexit "_fct: Function <$funct_> is not defined" ;; esac }