mkCTM revision 18110
1#!/usr/local/bin/tclsh7.4 2 3############################################################################# 4### Add something 5############################################################################# 6# Type Name Mode User Group Barf Size Hash 7 8proc CTMadd {t n m u g b s h} { 9 global fo_files fo_mkdir changes CTMref 10 11 puts stderr "A $b $t $n" 12 incr changes 13 14 if {$t == "d"} { 15 puts $fo_mkdir "CTMDM $n $u $g $m" 16 } elseif {$t == "f"} { 17 puts $fo_files "CTMFM $n $u $g $m $h $s" 18 flush $fo_files 19 exec cat $CTMref/$n >@ $fo_files 20 puts $fo_files "" 21 } else { 22 puts "confused in CTMadd" 23 exit 0 24 } 25} 26 27############################################################################# 28### Delete something 29############################################################################# 30# Type Name Mode User Group Barf Size Hash 31 32proc CTMdel {t n m u g b s h} { 33 global fo_del fo_rmdir changes damage max_damage CTMlock 34 35 puts stderr "D $b $t $n" 36 incr damage 37 incr changes 38 39 if {$damage > $max_damage} { 40 exec rm -f $CTMlock 41 return 42 } 43 if {$t == "d"} { 44 puts $fo_rmdir "CTMDR $n" 45 } elseif {$t == "f"} { 46 puts $fo_del "CTMFR $n $h" 47 } else { 48 puts "confused in CTMdel" 49 exit 0 50 } 51} 52 53############################################################################# 54### Change something 55############################################################################# 56# Type Name Mode User Group Barf Size Hash 57 58proc CTMchg {t1 n1 m1 u1 g1 b1 s1 h1 t2 n2 m2 u2 g2 b2 s2 h2} { 59 global fo_files CTMref CTMcopy changes damage CTMscratch 60 61 # Ignore attribute changes for directories 62 if {$t1 == "d" && $t2 == "d"} return 63 64 # turn file into dir or vice versa... 65 if {$t1 != $t2} { 66 CTMdel $t1 $n1 $m1 $u1 $g1 $b1 $s1 $h1 67 CTMadd $t2 $n2 $m2 $u2 $g2 $b2 $s2 $h2 68 return 69 } 70 71 # only files allowed past this poing... 72 if {$t1 != "f" && $t2 != "f"} { 73 puts "confused in CTMchg" 74 exit 0 75 } 76 77 # Ignore attribute changes for files 78 if {"x$h1" == "x$h2" && $s1 == $s2} return 79 80 if {$s2 == 0} { incr damage } 81 incr changes 82 83 # If diff will deal with it... 84 if {$b1 == "0" && $b2 == "0"} { 85 set i [catch "exec diff -n $CTMcopy/$n1 $CTMref/$n2 > $CTMscratch" j] 86 set s [file size $CTMscratch] 87 if {$s < $s2} { 88 puts stderr "E $b1$b2 $t1$t2 $n1" 89 puts $fo_files "CTMFN $n1 $u2 $g2 $m2 $h1 $h2 $s" 90 flush $fo_files 91 exec cat $CTMscratch >@ $fo_files 92 puts $fo_files "" 93 return 94 } 95 } 96 puts stderr "R $b1$b2 $t1$t2 $n1" 97 puts $fo_files "CTMFS $n2 $u2 $g2 $m2 $h1 $h2 $s2" 98 flush $fo_files 99 exec cat $CTMref/$n2 >@ $fo_files 100 puts $fo_files "" 101} 102 103############################################################################# 104### Do we already have this delta ? 105############################################################################# 106 107proc find_delta {nbr} { 108 global CTMname CTMdest 109 if {[file exists [format "%s/$CTMname.%04d" $CTMdest $nbr]]} { return 1 } 110 if {[file exists [format "%s/$CTMname.%04d.gz" $CTMdest $nbr]]} { return 1 } 111 return 0 112} 113 114############################################################################# 115### The top level code... 116############################################################################# 117 118set CTMSW /home/ctm/SW 119 120cd $CTMSW 121 122# Defaults... 123set CTMapply 1 124set CTMdont {^///} 125set CTMmail {} 126set CTMqueue {} 127set CTMqueuemail {} 128set CTMmaxctm 10000000 129set CTMmaxmsg 100000 130set CTMsuff {} 131set CTMdate [exec date -u +%Y%m%d%H%M%SZ] 132set CTMtmp {} 133set CTMcopy {} 134set CTMdest {} 135set CTMprefix . 136set CTMtest 0 137set CTMspecial 0 138set CTMscan . 139set CTMfirst 0 140set max_damage 1200 141 142set damage 0 143set changes 0 144 145exec sh -c "date -u '+%y%m%d%H%M%S $argv'" >> /home/ctm/log 146source $argv 147 148if {$CTMtmp == ""} { 149 set CTMtmp $CTMSW/../tmp/${CTMname}_${CTMsuff} 150} 151if {$CTMcopy == ""} { 152 set CTMcopy $CTMSW/../$CTMname 153} 154if {$CTMdest == ""} { 155 set CTMdest $CTMSW/../CTM-pub/$CTMname 156} 157 158# Make sure we only run one at a time... 159 160set CTMlock Lck.${CTMname}.${CTMdate}.[pid] 161exec rm -f ${CTMlock} 162exec echo starting > ${CTMlock} 163if {[catch "exec ln $CTMlock LCK.$CTMname" a]} { 164 puts "Not going, lock exists..." 165 exec rm -f $CTMlock 166 exit 0 167} 168exec rm -f $CTMlock 169set CTMlock LCK.$CTMname 170 171set CTMscratch ${CTMtmp}.tmp 172 173while 1 { 174 if { ! $CTMspecial} { 175 if {$CTMfirst} { 176 set CTMnbr 0 177 } else { 178 set CTMnbr [lindex [exec cat $CTMcopy/.ctm_status] 1] 179 } 180 181 if {$CTMnbr > 0 && ![find_delta $CTMnbr]} { 182 puts "$CTMname delta $CTMnbr doesn't exist..." 183 exec rm -f $CTMlock 184 exit 0 185 } 186 187 incr CTMnbr 188 189 if {[find_delta $CTMnbr]} { 190 puts "$CTMname delta $CTMnbr does already exist..." 191 exec rm -f $CTMlock 192 exit 0 193 } 194 195 set fo [open $CTMref/.ctm_status w] 196 puts $fo "$CTMname $CTMnbr" 197 close $fo 198 incr changes -1 199 200 } else { 201 set CTMnbr [lindex [exec cat $CTMref/.ctm_status] 1] 202 } 203 204 if {"$CTMcopy" == "" } { 205 set f1 [open /dev/null] 206 } else { 207 set f1 [open "| ./ctm_scan $CTMcopy $CTMscan"] 208 } 209 210 puts "Doing CTMname $CTMname CTMnbr $CTMnbr$CTMsuff CTMdate $CTMdate" 211 flush stdout 212 exec sh -c "rm -f ${CTMtmp}.* ${CTMtmp}:*" >&@ stdout 213 214 set f2 [open "| ./ctm_scan $CTMref $CTMscan"] 215 216 set fo_del [open $CTMtmp.del w] 217 set fo_rmdir [open $CTMtmp.rmdir w] 218 set fo_mkdir [open $CTMtmp.mkdir w] 219 set fo_files [open $CTMtmp.files w] 220 221 set l1 "" 222 set l2 "" 223 224 while 1 { 225 226 if {$l1 == ""} {gets $f1 l1} 227 228 if {$l2 == ""} {gets $f2 l2} 229 230 if {$l1 == "" && $l2 == ""} break 231 232 set n1 [lindex $l1 1] 233 set n2 [lindex $l2 1] 234 235 if {[regexp $CTMdont /$n1]} { set l1 "" ; continue } 236 if {[regexp $CTMdont /$n2]} { set l2 "" ; continue } 237 238 # they're all the same... 239 if {$l1 == $l2} { set l1 "" ; set l2 "" ; continue } 240 241 if {$l1 == "" } { eval CTMadd $l2 ; set l2 "" ; continue } 242 243 if {$l2 == "" } { eval CTMdel $l1 ; set l1 "" ; continue } 244 245 # if the name is the same we're safe... 246 if {$n1 == $n2} { 247 eval CTMchg $l1 $l2 248 set l1 "" 249 set l2 "" 250 continue 251 } 252 253 # To avoid this anomaly: 254 # A - d src/gnu/lib/libreadline/readline/Attic 255 # A 0 f src/gnu/lib/libreadline/readline/Attic/readline.h,v 256 # A 0 f src/gnu/lib/libreadline/readline.c,v 257 # D 0 f src/gnu/lib/libreadline/readline/readline.h,v 258 # D 0 f src/gnu/lib/libreadline/readline.c,v 259 # we have to make things somewhat complicated... 260 261 # if they have the same number of components... 262 set ll1 [llength [split $n1 /]] 263 set ll2 [llength [split $n2 /]] 264 if {$ll1 == $ll2} { 265 if {$n1 < $n2 } { 266 eval CTMdel $l1 ; set l1 "" ; continue 267 } else { 268 eval CTMadd $l2 ; set l2 "" ; continue 269 } 270 } 271 if {$ll1 < $ll2} { 272 eval CTMadd $l2 ; set l2 "" ; continue 273 } else { 274 eval CTMdel $l1 ; set l1 "" ; continue 275 } 276 } 277 278 close $fo_del 279 close $fo_rmdir 280 close $fo_mkdir 281 close $fo_files 282 283 if {$damage > $max_damage} { 284 puts "Too much damage: $damage deletes" 285 exec sh -c "rm -f ${CTMtmp}.*" 286 exec rm -f $CTMlock 287 exit 0 288 } 289 290 if {!$changes} { 291 puts "no changes" 292 exec sh -c "rm -f ${CTMtmp}.*" 293 exec rm -f $CTMlock 294 exit 0 295 } 296 297 exec echo CTM_BEGIN 2.0 $CTMname $CTMnbr $CTMdate $CTMprefix > $CTMtmp.begin 298 299 puts "Assembling delta" 300 flush stdout 301 set nm [format "%s.%04d%s" $CTMname $CTMnbr $CTMsuff] 302 303 set fdout [open "| /sbin/md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz" w] 304 305 foreach i {begin del rmdir mkdir files} { 306 exec cat $CTMtmp.$i >@$fdout 307 } 308 puts $fdout "CTM_END " nonewline 309 close $fdout ; unset fdout 310 311 exec sh -c "rm -f ${CTMtmp}.*" >&@ stdout 312 313 if {$CTMtest} { 314 puts "testing, stopping now." 315 exec rm -f $CTMlock 316 exit 0 317 } 318 if {$CTMapply} { 319 puts "Applying delta" 320 flush stdout 321 exec echo now applying > $CTMlock 322 exec sh -e -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >&@ stdout 323 exec echo did apply > $CTMlock 324 } 325 puts "Moving delta" 326 flush stdout 327 exec mv ${CTMtmp}:${nm}.gz $CTMdest/.CTMtmp_${nm}.gz >&@ stdout 328 exec mv $CTMdest/.CTMtmp_${nm}.gz $CTMdest/${nm}.gz >&@ stdout 329 exec echo moved > $CTMlock 330 331 if {$CTMmail != ""} { 332 puts "Mailing delta" 333 flush stdout 334 exec $CTMSW/ctm_smail -m $CTMmaxmsg -c $CTMmaxctm $CTMdest/${nm}.gz $CTMmail >&@ stdout 335 if {$CTMqueue != "" && $CTMqueuemail != ""} { 336 puts "Queueing delta" 337 flush stdout 338 exec $CTMSW/ctm_smail -m $CTMmaxmsg -c $CTMmaxctm -q $CTMqueue $CTMdest/${nm}.gz $CTMqueuemail >&@ stdout 339 } 340 } 341 exec echo mailed > $CTMlock 342 343 # If we did an absolute delta: stop. 344 if {$CTMsuff != ""} break 345 346 # Make a absolute delta (!) every 100 deltas 347 if {$CTMnbr == 0 || ($CTMnbr % 100)} break 348 349 # Make an absolute delta too... 350 set CTMref $CTMcopy 351 set CTMsuff A 352 set CTMcopy "" 353 set CTMmail "" 354 set CTMqueue "" 355 set CTMqueuemail "" 356 set CTMapply 0 357 set CTMspecial 1 358 exec rm -f $CTMlock 359} 360puts "done." 361exec rm -f $CTMlock 362