openpkg/lsync

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
parent 13
cb59d6afeb61
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     1 #!@l_prefix@/lib/openpkg/bash
     2 ##
     3 ##  lsync -- Access Layer Synchronization Tool
     4 ##  Copyright (c) 2000-2012 OpenPKG GmbH <http://openpkg.com/>
     5 ##
     6 ##  This software is property of the OpenPKG GmbH, DE MUC HRB 160208.
     7 ##  All rights reserved. Licenses which grant limited permission to use,
     8 ##  copy, modify and distribute this software are available from the
     9 ##  OpenPKG GmbH.
    10 ##
    11 ##  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
    12 ##  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    13 ##  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    14 ##  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
    15 ##  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    16 ##  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    17 ##  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    18 ##  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    19 ##  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    20 ##  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    21 ##  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    22 ##  SUCH DAMAGE.
    23 ##
    25 ##
    26 ##  filesystem hierarchy configuration
    27 ##
    29 #   program name and version/date
    30 progname="lsync"
    31 progvers="1.0.4"
    32 progdate="04-Aug-2001"
    34 #   root directory
    35 #   (if empty, .lsyncrc files provide default)
    36 root=""
    38 #   subdirectory where packages are physically installed
    39 pkgdir="PKG"
    41 #   subdirectories which are synchronized between physically
    42 #   installed package areas and access layer
    43 subdirs="bin,sbin,man,info,include,lib"
    45 ##
    46 ##  command line option parsing
    47 ##
    49 #   default run-time modes
    50 nop=0
    51 quiet=0
    52 trace=0
    53 help=''
    54 init=0
    55 uninstall=0
    56 local=0
    58 #   be aware of .lsyncrc files
    59 cwd=`pwd`
    60 while [ 1 ]; do
    61     if [ -f "$cwd/.lsyncrc" ]; then
    62         set -- `cat $cwd/.lsyncrc` "$@"
    63     fi
    64     [ ".$cwd" = ./ ] && break
    65     cwd=`echo $cwd | sed -e 's;/[^/]*$;;' -e 's;^$;/;'`
    66 done
    67 if [ ".$HOME" != . -a -f "$HOME/.lsyncrc" ]; then
    68     set -- `cat $HOME/.lsyncrc` "$@"
    69 fi
    71 #   iterate over argument line
    72 for opt
    73 do
    74     case $opt in
    75         -*=*) arg=`echo "$opt" | sed 's/^[-_a-zA-Z0-9]*=//'` ;;
    76            *) arg='' ;;
    77     esac
    78     case $opt in
    79         -n|--nop       ) nop=1         ;;
    80         -q|--quiet     ) quiet=1       ;;
    81         -t|--trace     ) trace=1       ;;
    82         -v|--version   ) version=1     ;;
    83         -h|--help      ) help="Usage"  ;;
    84         -i|--init      ) init=1        ;;
    85         -u|--uninstall ) uninstall=1   ;;
    86         -l|--local     ) local=1       ;;
    87         --root=*       ) root=$arg     ;;
    88         --pkgdir=*     ) pkgdir=$arg   ;;
    89         --subdirs=*    ) subdirs=$arg  ;;
    90         *              ) help="Invalid option \`$opt'"; break ;;
    91     esac
    92 done
    94 #   error or usage message
    95 if [ ".$help" != . ]; then
    96     if [ ".$help" != ".Usage" ]; then
    97         echo "$progname:ERROR: $help" 1>&2
    98     fi
    99     cat 1>&2 <<EOT
   100 Usage: $progname [options]
   102 Global options:
   103   --version,   -v   display tool version information
   104   --help,      -h   display usage information
   105   --init,      -i   create an initial directory hierarchy
   107 Run-time options:
   108   --nop,       -n   perform no filesystem operations
   109   --quiet,     -q   display no verbose messages
   110   --trace,     -t   display performed filesystem operations
   111   --local,     -l   process a local package area only
   112   --uninstall, -u   uninstall all files
   114 Filesystem options:
   115   --root=DIR        override root directory
   116   --pkgdir=DIR      override package sub-directory
   117   --subdirs=DIR     override synchronized sub-directories
   119 Current configuration:
   120   root directory:       $root
   121   package root subdir:  $pkgdir
   122   synchronized subdirs: $subdirs
   123 EOT
   124     if [ ".$help" != ".Usage" ]; then
   125         exit 2
   126     else
   127         exit 0
   128     fi
   129 fi
   131 #   version information
   132 if [ ".$version" = .1 ]; then
   133     echo "$progname $progvers ($progdate)"
   134     exit 0
   135 fi
   137 #   make sure a root directory was found or specified
   138 if [ ".$root" = . ]; then
   139     echo "$progname:ERROR: no root directory specified!" 1>&2
   140     echo "$progname:HINT: use --root=DIR option explicitly on command line" 1>&2
   141     echo "$progname:HINT: or implicitly inside an .lsyncrc file in your home" 1>&2
   142     echo "$progname:HINT: directory or in any parent directory." 1>&2
   143     exit 3
   144 fi
   146 ##
   147 ##  helper functions
   148 ##
   150 display_hd () {
   151     if [ ".$headline" != . ]; then
   152         if [ ".$quiet" = .0 ]; then
   153             echo "$headline"
   154         fi
   155         headline=''
   156     fi
   157 }
   159 display_op () {
   160     if [ ".$quiet" = .0 ]; then
   161         echo "  $@"
   162     fi
   163 }
   165 display_warning () {
   166     echo "$progname:WARNING: $*" 1>&2
   167 }
   169 display_error () {
   170     echo "$progname:ERROR: $*" 1>&2
   171 }
   173 perform_op () {
   174     if [ ".$trace" = .1 ]; then
   175         echo "  \$ $@"
   176     fi
   177     if [ ".$nop" = .0 ]; then
   178         eval "$@"
   179     fi
   180 }
   182 ##
   183 ##  main processing
   184 ##
   186 #   extend a "man" subdir to a complete list with subdirs
   187 #   in order to avoid special cases in the loop processing
   188 manex=''
   189 if [ ".$init" = .1 ]; then
   190     manex='man'
   191 fi
   192 for i in 1 2 3 4 5 6 7 8; do
   193     manex="$manex,man/man$i"
   194 done
   195 manex=`echo $manex | sed -e 's;^,;;'`
   196 subdirs=`echo $subdirs | sed -e "s;man;$manex;"`
   198 #   special processing: create initial hierarchy
   199 if [ ".$init" = .1 ]; then
   200     if [ ! -d $root ]; then
   201         echo "creating $root"
   202         perform_op "mkdir $root" || exit 1
   203     fi
   204     for subdir in $pkgdir `IFS=,; echo $subdirs`; do
   205         if [ ! -d "$root/$subdir" ]; then
   206             echo "creating $root/$subdir"
   207             perform_op "mkdir $root/$subdir" || exit 1
   208         fi
   209     done
   210     exit 0
   211 fi
   213 #   make sure the root directory actually exists
   214 if [ ! -d "$root" ]; then
   215     display_warning "root directory \`$root' does not exist"
   216     exit 3
   217 fi
   219 #   if processing is restricted to a local package area, pre-determine its name
   220 if [ ".$local" = .1 ]; then
   221    realroot=`cd $root; pwd`
   222    realthis=`pwd`
   223    pkgname=`expr "$realthis" : "^$realroot/$pkgdir/\\([^/]*\\).*"`
   224    if [ ".$pkgname" = . ]; then
   225        display_error "you are not staying under a local package sub-directory"
   226        exit 3
   227    fi
   228 fi
   230 #   now perform the synchronization for each sub-directory...
   231 for subdir in `IFS=,; echo $subdirs`; do
   232     headline="$root/$subdir:"
   234     #   make sure the subdir actually exists in the access layer
   235     if [ ! -d "$root/$subdir" ]; then
   236         display_warning "access layer directory \`$root/$subdir' does not exist"
   237         continue
   238     fi
   240     #
   241     #   PASS 1: remove dangling symbolic links in access layer
   242     #
   244     #   iterate over all symlinks in the access layer subdir
   245     for link in . `ls "$root/$subdir/" | sed -e "s;^$root/$subdir/*;;g"`; do
   246         test ".$link" = ".." && continue
   248         #   determine the target file of the symlink
   249         target=`ls -l "$root/$subdir/$link" 2>/dev/null | sed -e 's;.*-> *;;'`
   250         if [ ".$target" = . ]; then
   251             display_warning "$root/$subdir/$link seems to be not a symbolic link"
   252             continue
   253         fi
   255         #   (optionally) make sure that link target points into local package area
   256         if [ ".$local" = .1 -a .`expr $target : "../$pkgdir/$pkgname/.*"` = .0 ]; then
   257             continue
   258         fi
   260         #   check whether link is valid, i.e., points to
   261         #   an existing target file or directory
   262         if [ ".$uninstall" = .1 ] ||\
   263            [ ! -f "$root/$subdir/$target" -a \
   264              ! -d "$root/$subdir/$target"      ]; then
   265             #   target no longer exists, so remove dangling symlink
   266             display_hd
   267             display_op "remove: $link -> $target"
   268             perform_op "rm -f $root/$subdir/$link"
   269         fi
   270     done
   272     #   if we are uninstalling only, our work is now done
   273     if [ ".$uninstall" = ".1" ]; then
   274         continue
   275     fi
   277     #
   278     #   PASS 2: create new symbolic links in access layer
   279     #
   281     #   calculate the corresponding reverse directory for the current subdir
   282     revdir=`echo $subdir | sed -e 's;[^/][^/]*;..;g'`
   284     #   iterate over all package directories
   285     for dir in . `ls "$root/$pkgdir/" | sed -e "s;^$root/$pkgdir/*;;g"`; do
   286         test ".$dir" = ".." && continue
   288         #   (optionally) make sure that we operate only for the local package area
   289         if [ ".$local" = .1 -a ".$dir" != ".$pkgname" ]; then
   290             continue
   291         fi
   293         #   skip all directories with appended version numbers
   294         #   in order to support manual versioning of packages
   295         case $dir in
   296             *-[0-9]* ) continue ;;
   297         esac
   299         #   skip if package directory or package sub-directories has sticky bit set
   300         if [ ".`ls -l -d $root/$pkgdir/$dir 2>/dev/null | cut -c10`" = .t ] ||\
   301            [ ".`ls -l -d $root/$pkgdir/$dir/$subdir 2>/dev/null | cut -c10`" = .t ]; then
   302             continue
   303         fi
   305         #   check whether the processed subdir exists in package area
   306         if [ -d "$root/$pkgdir/$dir/$subdir" ]; then
   308             #   iterate over all files/directories in package's subdir
   309             for file in . `ls "$root/$pkgdir/$dir/$subdir/" |\
   310                            sed -e "s;^$root/$pkgdir/$dir/$subdir/*;;g"`; do
   311                 test ".$file" = ".." && continue
   313                 #   calculate the access layer symlink target
   314                 target="$revdir/$pkgdir/$dir/$subdir/$file"
   316                 #   check whether a possibly conflicting symlink exists
   317                 exlink=`ls -l $root/$subdir/$file 2>/dev/null`
   318                 if [ ".$exlink" != . ]; then
   319                     extarget=`echo $exlink | sed -e 's;.*-> *;;'`
   320                     if [ ".$extarget" = . ]; then
   321                         display_warning "$root/$subdir/$file exits, but seems to be not a symbolic link"
   322                     elif [ ".$extarget" != ".$target" ]; then
   323                         display_hd
   324                         display_op "conflict: $file -> $extarget [existing]"
   325                         display_op "          $file -> $target [alternative]"
   326                     fi
   327                     continue
   328                 fi
   330                 #   create new symlink in access layer
   331                 display_hd
   332                 display_op "create: $file -> $target"
   333                 perform_op "cd $root/$subdir && ln -s $target $file"
   334             done
   335         fi
   336     done
   337 done

mercurial