openpkg/lsync

Thu, 05 Nov 2009 13:42:13 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 05 Nov 2009 13:42:13 +0100
changeset 237
76b4896bea63
child 428
f880f219c566
permissions
-rw-r--r--

Resynchronize with upstream package maintainer version.
This is needed due to large changeset after upgrade of vendor
distribution from version 1.1.* to 1.2.*.

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

mercurial