openpkg/lsync

Wed, 21 Sep 2011 13:51:49 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 21 Sep 2011 13:51:49 +0200
changeset 373
b8e8f9dbbfd3
child 428
f880f219c566
permissions
-rw-r--r--

Update version and integrate setuid logic from upstream package vendor.

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

mercurial