aboutsummaryrefslogtreecommitdiff
path: root/scripts/flxfix
blob: 8952c39f8c11acace7da3d2e70e9a822f933821a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/bin/bash

# flxfix 0.2 - 2005/04/17 - Willy Tarreau <willy@ant-computing.com>
# Generates a shell script from a difference between two trees so that the last
# one becomes as close to the first one as possible. Second usage is to rebuild
# all the meta-data from a signature.
#
# usage:
#   flx check <reference> <tobefixed> | flxfix [ -R ] > fix.sh
#       Use -R to swap the two trees
#   flx sign <reference> | flxfix -n > create.sh
#       Generates a shell script which rebuilds the meta-data from the tree's
#       signature.
#
# WARNING: this script does not understand flx-0.7's extended encoding of
#          unprintable characters.


entryisdiff=1
restoredate=1
unset mustswap ignoreuid

# usage : fixperms $perm $uid $gid $date $name
function fixperms {
   echo touch ${restoredate:+-t \"$(date -d "Jan 1 00:00:$4 UTC 1970" +"%Y%m%d%H%M.%S" )\"} $5
   [ -z "$ignoreuid" ] && echo chown $2:$3 $5
   echo chmod $1 $5
}

# swap diff direction : -/+, </>
function swap {
   local x
   x=${1/</.}; x=${x/>/<}; x=${x/./>}
   x=${x/-/.}; x=${x/+/-}; x=${x/./+}
   echo -n $x
}

# usage: usage progname exitcode
function usage {
   echo "$1: Generates a script to rebuild the meta-data from an flx signature"
   echo "Usage:"
   echo "    flx check <reference> <tobefixed> | $1 > fix.sh"
   echo "    flx check <tobefixed> <reference> | $1 -R > fix.sh"
   echo "    flx sign  <reference> | $1 -n > new.sh"
   echo "    cat old-signature.lst | $1 -n > new.sh"
   echo ""
   echo "Options:"
   echo "    -R    swap the two trees"
   echo "    -n    recreate a new tree from a single signature"
   echo "    -t    do not restore timestamp"
   echo "    -u    do not restore uid/gid"

   exit $2
}


while [ $# -gt 0 ]; do
  if [ "x$1" = "x-R" ]; then
     mustswap=1
  elif [ "x$1" = "x-n" ]; then
     unset entryisdiff
  elif [ "x$1" = "x-u" ]; then
     ignoreuid=1
  elif [ "x$1" = "x-t" ]; then
     unset restoredate
  elif [ "x$1" = "x-h" ]; then
     usage "${0##*/}" 0
  else
     echo "Warning: ignoring unknown option: $1"
     usage "${0##*/}" 1
  fi
  shift
done

# trick: we only reference the 'chg' variable if 'entryisdiff' is set.
while read ${entryisdiff:+chg} type perm uid gid size sign date name link rest; do
   if [ -z "$entryisdiff" ]; then
      chg='-'
   elif [ -n "$mustswap" ]; then
      chg=$(swap $chg)
   fi

   if [ "x$rest" != "x" -o "x$type" != "xl" -a "x$link" != "x" ]; then
	echo "# Ignoring too long line : $REPLY"
	continue
   elif [ "x$name" = "x" -o "x$type" = "xl" -a "x$link" = "x" ]; then
	echo "# Ignoring too short line : $REPLY"
	continue
   fi

   if [ x$chg = x+ ]; then
      # new entry which wasn't in <reference>, should be removed
      if [ x$type = xd ]; then
         # theorically, we should use rm -rf to suppress all children
         echo rmdir $name
      else
         echo rm -f $name
      fi
   elif [ x$chg = x- ]; then
      # missing entry, sometimes we can rebuild them
      if [ x$type = xl ]; then
         # we'll rebuild a symbolic link
         echo ln -s $link $name
         [ -z "$ignoreuid" ] && echo chown -h $uid:$gid $name
      elif [ x$type = xd ]; then
         # we'll rebuild a directory
         echo mkdir -p $name
         fixperms $perm $uid $gid $date $name
      elif [ x$type = x- ]; then
         if [ x$size = x0 ]; then
            # we can also rebuild files, only if they are empty
            fixperms $perm $uid $gid $date $name
         else
            echo "echo \"Cannot create missing file $name ($size bytes).\""
         fi
      elif [ x$type = xc -o x$type = xb -o x$type = xf ]; then
         # we'll rebuild nodes
         echo mknod $name ${type/f/p} ${size/,/ }
         fixperms $perm $uid $gid $date $name
      else
         echo "echo \"Cannot fix $name, unsupported file type : $type\""
      fi
   elif [ x$chg = x\< ]; then
      # entry has changed
      if [ x$type = xl ]; then
         # we'll destroy and rebuild a symbolic link
         echo rm -f $name
         echo ln -s $link $name
         [ -z "$ignoreuid" ] && echo chown -h $uid:$gid $name
      elif [ x$type = xc -o x$type = xb -o x$type = xf ]; then
         # we'll destroy and rebuild nodes
         echo rm -f $name
         echo mknod $name ${type/f/p} ${size/,/ }
         fixperms $perm $uid $gid $date $name
      else
         # in other cases, we only try to fix perms
         fixperms $perm $uid $gid $date $name
      fi
   fi
done