mirror of
https://github.com/freebsd/freebsd-src
synced 2024-11-05 18:22:52 +00:00
Improve mkctm.c so we can use it, and start using it.
This should help quite a bit on the load. Notice that some minor changes in config files will be needed. Contact me for details.
This commit is contained in:
parent
bf8919163f
commit
9c0f44a5b3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19813
4 changed files with 173 additions and 335 deletions
|
@ -2,6 +2,7 @@
|
|||
PROG= mkctm
|
||||
SRCS= mkctm.c
|
||||
LDADD= -lmd
|
||||
NOMAN= 1
|
||||
CFLAGS= -g -Wall
|
||||
|
||||
test: mkctm
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
set CTMname gnats
|
||||
set CTMref /home/gnats
|
||||
set CTMdest $CTMSW/../CTM-pub/$CTMname
|
||||
#set CTMdont {}
|
||||
set CTMignore {\.lock$}
|
||||
set CTMmail ctm-gnats@freebsd.org
|
||||
|
|
|
@ -1,105 +1,5 @@
|
|||
#!/usr/local/bin/tclsh7.4
|
||||
|
||||
#############################################################################
|
||||
### Add something
|
||||
#############################################################################
|
||||
# Type Name Mode User Group Barf Size Hash
|
||||
|
||||
proc CTMadd {t n m u g b s h} {
|
||||
global fo_files fo_mkdir changes CTMref
|
||||
|
||||
puts stderr "A $b $t $n"
|
||||
incr changes
|
||||
|
||||
if {$t == "d"} {
|
||||
puts $fo_mkdir "CTMDM $n $u $g $m"
|
||||
} elseif {$t == "f"} {
|
||||
puts $fo_files "CTMFM $n $u $g $m $h $s"
|
||||
flush $fo_files
|
||||
exec cat $CTMref/$n >@ $fo_files
|
||||
puts $fo_files ""
|
||||
} else {
|
||||
puts "confused in CTMadd"
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
### Delete something
|
||||
#############################################################################
|
||||
# Type Name Mode User Group Barf Size Hash
|
||||
|
||||
proc CTMdel {t n m u g b s h} {
|
||||
global fo_del fo_rmdir changes damage max_damage CTMlock
|
||||
|
||||
puts stderr "D $b $t $n"
|
||||
incr damage
|
||||
incr changes
|
||||
|
||||
if {$damage > $max_damage} {
|
||||
exec rm -f $CTMlock
|
||||
return
|
||||
}
|
||||
if {$t == "d"} {
|
||||
puts $fo_rmdir "CTMDR $n"
|
||||
} elseif {$t == "f"} {
|
||||
puts $fo_del "CTMFR $n $h"
|
||||
} else {
|
||||
puts "confused in CTMdel"
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
### Change something
|
||||
#############################################################################
|
||||
# Type Name Mode User Group Barf Size Hash
|
||||
|
||||
proc CTMchg {t1 n1 m1 u1 g1 b1 s1 h1 t2 n2 m2 u2 g2 b2 s2 h2} {
|
||||
global fo_files CTMref CTMcopy changes damage CTMscratch
|
||||
|
||||
# Ignore attribute changes for directories
|
||||
if {$t1 == "d" && $t2 == "d"} return
|
||||
|
||||
# turn file into dir or vice versa...
|
||||
if {$t1 != $t2} {
|
||||
CTMdel $t1 $n1 $m1 $u1 $g1 $b1 $s1 $h1
|
||||
CTMadd $t2 $n2 $m2 $u2 $g2 $b2 $s2 $h2
|
||||
return
|
||||
}
|
||||
|
||||
# only files allowed past this poing...
|
||||
if {$t1 != "f" && $t2 != "f"} {
|
||||
puts "confused in CTMchg"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Ignore attribute changes for files
|
||||
if {"x$h1" == "x$h2" && $s1 == $s2} return
|
||||
|
||||
if {$s2 == 0} { incr damage }
|
||||
incr changes
|
||||
|
||||
# If diff will deal with it...
|
||||
if {$b1 == "0" && $b2 == "0"} {
|
||||
set i [catch "exec diff -n $CTMcopy/$n1 $CTMref/$n2 > $CTMscratch" j]
|
||||
set s [file size $CTMscratch]
|
||||
if {$s < $s2} {
|
||||
puts stderr "E $b1$b2 $t1$t2 $n1"
|
||||
puts $fo_files "CTMFN $n1 $u2 $g2 $m2 $h1 $h2 $s"
|
||||
flush $fo_files
|
||||
exec cat $CTMscratch >@ $fo_files
|
||||
puts $fo_files ""
|
||||
return
|
||||
}
|
||||
}
|
||||
puts stderr "R $b1$b2 $t1$t2 $n1"
|
||||
puts $fo_files "CTMFS $n2 $u2 $g2 $m2 $h1 $h2 $s2"
|
||||
flush $fo_files
|
||||
exec cat $CTMref/$n2 >@ $fo_files
|
||||
puts $fo_files ""
|
||||
}
|
||||
|
||||
#############################################################################
|
||||
### Do we already have this delta ?
|
||||
#############################################################################
|
||||
|
@ -121,7 +21,8 @@ cd $CTMSW
|
|||
|
||||
# Defaults...
|
||||
set CTMapply 1
|
||||
set CTMdont {^///}
|
||||
set CTMignore {^///}
|
||||
set CTMbogus {\.core$}
|
||||
set CTMmail {}
|
||||
set CTMqueue {}
|
||||
set CTMqueuemail {}
|
||||
|
@ -137,13 +38,13 @@ set CTMtest 0
|
|||
set CTMspecial 0
|
||||
set CTMscan .
|
||||
set CTMfirst 0
|
||||
set max_damage 1200
|
||||
set max_damage 100
|
||||
|
||||
set damage 0
|
||||
set changes 0
|
||||
|
||||
exec sh -c "date -u '+%y%m%d%H%M%S $argv'" >> /home/ctm/log
|
||||
source $argv
|
||||
exec sh -c "date -u '+%y%m%d%H%M%S $argv'" >> ${CTMSW}/log
|
||||
|
||||
if {$CTMtmp == ""} {
|
||||
set CTMtmp $CTMSW/../tmp/${CTMname}_${CTMsuff}
|
||||
|
@ -163,7 +64,7 @@ exec echo starting > ${CTMlock}
|
|||
if {[catch "exec ln $CTMlock LCK.$CTMname" a]} {
|
||||
puts "Not going, lock exists..."
|
||||
exec rm -f $CTMlock
|
||||
exit 0
|
||||
exit 1
|
||||
}
|
||||
exec rm -f $CTMlock
|
||||
set CTMlock LCK.$CTMname
|
||||
|
@ -181,7 +82,7 @@ while 1 {
|
|||
if {$CTMnbr > 0 && ![find_delta $CTMnbr]} {
|
||||
puts "$CTMname delta $CTMnbr doesn't exist..."
|
||||
exec rm -f $CTMlock
|
||||
exit 0
|
||||
exit 1
|
||||
}
|
||||
|
||||
incr CTMnbr
|
||||
|
@ -189,7 +90,7 @@ while 1 {
|
|||
if {[find_delta $CTMnbr]} {
|
||||
puts "$CTMname delta $CTMnbr does already exist..."
|
||||
exec rm -f $CTMlock
|
||||
exit 0
|
||||
exit 1
|
||||
}
|
||||
|
||||
set fo [open $CTMref/.ctm_status w]
|
||||
|
@ -201,114 +102,28 @@ while 1 {
|
|||
set CTMnbr [lindex [exec cat $CTMref/.ctm_status] 1]
|
||||
}
|
||||
|
||||
if {"$CTMcopy" == "" } {
|
||||
set f1 [open /dev/null]
|
||||
} else {
|
||||
set f1 [open "| ./ctm_scan $CTMcopy $CTMscan"]
|
||||
}
|
||||
|
||||
puts "Doing CTMname $CTMname CTMnbr $CTMnbr$CTMsuff CTMdate $CTMdate"
|
||||
flush stdout
|
||||
exec sh -c "rm -f ${CTMtmp}.* ${CTMtmp}:*" >&@ stdout
|
||||
|
||||
set f2 [open "| ./ctm_scan $CTMref $CTMscan"]
|
||||
|
||||
set fo_del [open $CTMtmp.del w]
|
||||
set fo_rmdir [open $CTMtmp.rmdir w]
|
||||
set fo_mkdir [open $CTMtmp.mkdir w]
|
||||
set fo_files [open $CTMtmp.files w]
|
||||
|
||||
set l1 ""
|
||||
set l2 ""
|
||||
|
||||
while 1 {
|
||||
|
||||
if {$l1 == ""} {gets $f1 l1}
|
||||
|
||||
if {$l2 == ""} {gets $f2 l2}
|
||||
|
||||
if {$l1 == "" && $l2 == ""} break
|
||||
|
||||
set n1 [lindex $l1 1]
|
||||
set n2 [lindex $l2 1]
|
||||
|
||||
if {[regexp $CTMdont /$n1]} { set l1 "" ; continue }
|
||||
if {[regexp $CTMdont /$n2]} { set l2 "" ; continue }
|
||||
|
||||
# they're all the same...
|
||||
if {$l1 == $l2} { set l1 "" ; set l2 "" ; continue }
|
||||
|
||||
if {$l1 == "" } { eval CTMadd $l2 ; set l2 "" ; continue }
|
||||
|
||||
if {$l2 == "" } { eval CTMdel $l1 ; set l1 "" ; continue }
|
||||
|
||||
# if the name is the same we're safe...
|
||||
if {$n1 == $n2} {
|
||||
eval CTMchg $l1 $l2
|
||||
set l1 ""
|
||||
set l2 ""
|
||||
continue
|
||||
}
|
||||
|
||||
# To avoid this anomaly:
|
||||
# A - d src/gnu/lib/libreadline/readline/Attic
|
||||
# A 0 f src/gnu/lib/libreadline/readline/Attic/readline.h,v
|
||||
# A 0 f src/gnu/lib/libreadline/readline.c,v
|
||||
# D 0 f src/gnu/lib/libreadline/readline/readline.h,v
|
||||
# D 0 f src/gnu/lib/libreadline/readline.c,v
|
||||
# we have to make things somewhat complicated...
|
||||
|
||||
# if they have the same number of components...
|
||||
set ll1 [llength [split $n1 /]]
|
||||
set ll2 [llength [split $n2 /]]
|
||||
if {$ll1 == $ll2} {
|
||||
if {$n1 < $n2 } {
|
||||
eval CTMdel $l1 ; set l1 "" ; continue
|
||||
} else {
|
||||
eval CTMadd $l2 ; set l2 "" ; continue
|
||||
}
|
||||
}
|
||||
if {$ll1 < $ll2} {
|
||||
eval CTMadd $l2 ; set l2 "" ; continue
|
||||
} else {
|
||||
eval CTMdel $l1 ; set l1 "" ; continue
|
||||
}
|
||||
}
|
||||
|
||||
close $fo_del
|
||||
close $fo_rmdir
|
||||
close $fo_mkdir
|
||||
close $fo_files
|
||||
|
||||
if {$damage > $max_damage} {
|
||||
puts "Too much damage: $damage deletes"
|
||||
exec sh -c "rm -f ${CTMtmp}.*"
|
||||
exec rm -f $CTMlock
|
||||
exit 0
|
||||
}
|
||||
|
||||
if {!$changes} {
|
||||
puts "no changes"
|
||||
exec sh -c "rm -f ${CTMtmp}.*"
|
||||
exec rm -f $CTMlock
|
||||
exit 0
|
||||
}
|
||||
|
||||
exec echo CTM_BEGIN 2.0 $CTMname $CTMnbr $CTMdate $CTMprefix > $CTMtmp.begin
|
||||
|
||||
puts "Assembling delta"
|
||||
flush stdout
|
||||
set nm [format "%s.%04d%s" $CTMname $CTMnbr $CTMsuff]
|
||||
|
||||
set fdout [open "| /sbin/md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz" w]
|
||||
|
||||
foreach i {begin del rmdir mkdir files} {
|
||||
exec cat $CTMtmp.$i >@$fdout
|
||||
set x1 $CTMcopy
|
||||
if {$x1 == ""} {
|
||||
exec mkdir ${CTMtmp}.dir
|
||||
set x1 ${CTMtmp}.dir
|
||||
}
|
||||
puts $fdout "CTM_END " nonewline
|
||||
close $fdout ; unset fdout
|
||||
set r1 [catch "exec ${CTMSW}/mkctm -I ${CTMignore} -B ${CTMbogus} -l ${CTMtmp}.log -D $max_damage $CTMname $CTMnbr . $CTMdate $x1 $CTMref | md5 -p | gzip -9 > ${CTMtmp}:${nm}.gz 2>@ stderr" r2]
|
||||
|
||||
exec sh -c "rm -f ${CTMtmp}.*" >&@ stdout
|
||||
if {$r1} {
|
||||
puts "problems, stopping now."
|
||||
puts "errorCode $errorCode"
|
||||
puts "$r2"
|
||||
exec rm -f $CTMlock
|
||||
exit 1
|
||||
}
|
||||
|
||||
puts "mkctm done"
|
||||
|
||||
if {$CTMtest} {
|
||||
puts "testing, stopping now."
|
||||
|
@ -319,7 +134,7 @@ while 1 {
|
|||
puts "Applying delta"
|
||||
flush stdout
|
||||
exec echo now applying > $CTMlock
|
||||
exec sh -e -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >&@ stdout
|
||||
exec sh -e -c "cd $CTMcopy ; $CTMSW/ctm -v -v -v ${CTMtmp}:${nm}.gz" >& ${CTMtmp}.apply
|
||||
exec echo did apply > $CTMlock
|
||||
}
|
||||
puts "Moving delta"
|
||||
|
@ -328,6 +143,8 @@ while 1 {
|
|||
exec mv $CTMdest/.CTMtmp_${nm}.gz $CTMdest/${nm}.gz >&@ stdout
|
||||
exec echo moved > $CTMlock
|
||||
|
||||
exec sh -c "rm -rf ${CTMtmp}.*" >&@ stdout
|
||||
|
||||
if {$CTMmail != ""} {
|
||||
puts "Mailing delta"
|
||||
flush stdout
|
||||
|
|
|
@ -1,12 +1,4 @@
|
|||
/* Still missing:
|
||||
*
|
||||
* Damage counter
|
||||
* Change counter
|
||||
* Time stamp
|
||||
* prefix
|
||||
* cmd-line args
|
||||
* %100 deltas
|
||||
* delta and Add are different. delta -> Equ.
|
||||
*
|
||||
* mkctm
|
||||
* -B regex Bogus
|
||||
|
@ -14,7 +6,7 @@
|
|||
* -D int Damage
|
||||
* -q decrease verbosity
|
||||
* -v increase verbosity
|
||||
* (-l str control logging.)
|
||||
* -l file logfile
|
||||
* name cvs-cur
|
||||
* prefix src/secure
|
||||
* dir1 "Soll"
|
||||
|
@ -38,7 +30,7 @@
|
|||
#include <signal.h>
|
||||
|
||||
#define DEFAULT_IGNORE "/CVS$|/\\.#|00_TRANS\\.TBL$"
|
||||
#define DEFAULT_BOGUS "\\.core$|\\.orig$|\\.rej$"
|
||||
#define DEFAULT_BOGUS "\\.core$|\\.orig$|\\.rej$|\\.o$"
|
||||
regex_t reg_ignore, reg_bogus;
|
||||
int flag_ignore, flag_bogus;
|
||||
|
||||
|
@ -46,6 +38,8 @@ int verbose;
|
|||
int damage, damage_limit;
|
||||
int change;
|
||||
|
||||
FILE *logf;
|
||||
|
||||
u_long s1_ignored, s2_ignored;
|
||||
u_long s1_bogus, s2_bogus;
|
||||
u_long s1_wrong, s2_wrong;
|
||||
|
@ -73,34 +67,35 @@ Usage(void)
|
|||
void
|
||||
print_stat(FILE *fd, char *pre)
|
||||
{
|
||||
fprintf(fd,"%sAvoided:\n",pre);
|
||||
fprintf(fd,"%s ignore: %5lu old %5lu new\n",
|
||||
fprintf(fd, "%sNames:\n", pre);
|
||||
fprintf(fd, "%s ignore: %5lu ref %5lu target\n",
|
||||
pre, s1_ignored, s2_ignored);
|
||||
fprintf(fd,"%s bogus: %5lu old %5lu new\n",
|
||||
fprintf(fd, "%s bogus: %5lu ref %5lu target\n",
|
||||
pre, s1_bogus, s2_bogus);
|
||||
fprintf(fd,"%s wrong: %5lu old %5lu new\n",
|
||||
fprintf(fd, "%s wrong: %5lu ref %5lu target\n",
|
||||
pre, s1_wrong, s2_wrong);
|
||||
fprintf(fd,"%sDelta:\n",pre);
|
||||
fprintf(fd,"%s new: %5lu dirs %5lu files %9lu plus\n",
|
||||
fprintf(fd, "%sDelta:\n", pre);
|
||||
fprintf(fd, "%s new: %5lu dirs %5lu files %9lu plus\n",
|
||||
pre, s_new_dirs, s_new_files, s_new_bytes);
|
||||
fprintf(fd,"%s del: %5lu dirs %5lu files %9lu minus\n",
|
||||
fprintf(fd, "%s del: %5lu dirs %5lu files %9lu minus\n",
|
||||
pre, s_del_dirs, s_del_files, s_del_bytes);
|
||||
fprintf(fd,"%s chg: %5lu files %9lu plus %9lu minus\n",
|
||||
fprintf(fd, "%s chg: %5lu files %9lu plus %9lu minus\n",
|
||||
pre, s_files_chg, s_bytes_add, s_bytes_del);
|
||||
fprintf(fd,"%s same: %5lu dirs %5lu files %9lu bytes\n",
|
||||
fprintf(fd, "%s same: %5lu dirs %5lu files %9lu bytes\n",
|
||||
pre, s_same_dirs, s_same_files, s_same_bytes);
|
||||
fprintf(fd,"%sMethod:\n",pre);
|
||||
fprintf(fd,"%s edit: %5lu files %9lu bytes %9lu saved\n",
|
||||
fprintf(fd, "%sMethod:\n", pre);
|
||||
fprintf(fd, "%s edit: %5lu files %9lu bytes %9lu saved\n",
|
||||
pre, s_edit_files, s_edit_bytes, s_edit_saves);
|
||||
fprintf(fd,"%s sub: %5lu files %9lu bytes\n",
|
||||
fprintf(fd, "%s sub: %5lu files %9lu bytes\n",
|
||||
pre, s_sub_files, s_sub_bytes);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
stat_info(int foo)
|
||||
{
|
||||
signal(SIGINFO,stat_info);
|
||||
print_stat(stderr,"INFO: ");
|
||||
signal(SIGINFO, stat_info);
|
||||
print_stat(stderr, "INFO: ");
|
||||
}
|
||||
|
||||
void DoDir(const char *dir1, const char *dir2, const char *name);
|
||||
|
@ -109,16 +104,16 @@ static struct stat st;
|
|||
static __inline struct stat *
|
||||
StatFile(char *name)
|
||||
{
|
||||
if (lstat(name,&st) < 0)
|
||||
err(1,"Couldn't stat %s\n",name);
|
||||
if (lstat(name, &st) < 0)
|
||||
err(1, "Couldn't stat %s\n", name);
|
||||
return &st;
|
||||
}
|
||||
|
||||
int
|
||||
dirselect(struct dirent *de)
|
||||
{
|
||||
if (!strcmp(de->d_name,".")) return 0;
|
||||
if (!strcmp(de->d_name,"..")) return 0;
|
||||
if (!strcmp(de->d_name, ".")) return 0;
|
||||
if (!strcmp(de->d_name, "..")) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -129,15 +124,16 @@ name_stat(const char *pfx, const char *dir, const char *name, struct dirent *de)
|
|||
strlen(de->d_name) + 3);
|
||||
struct stat *st;
|
||||
|
||||
strcpy(buf,dir);
|
||||
strcat(buf,"/"); strcat(buf,name);
|
||||
strcat(buf,"/"); strcat(buf,de->d_name);
|
||||
strcpy(buf, dir);
|
||||
strcat(buf, "/"); strcat(buf, name);
|
||||
strcat(buf, "/"); strcat(buf, de->d_name);
|
||||
st = StatFile(buf);
|
||||
printf("%s %s%s %lu %lu %o",
|
||||
printf("%s %s%s %u %u %o",
|
||||
pfx, name, de->d_name,
|
||||
st->st_uid, st->st_gid, st->st_mode & ~S_IFMT);
|
||||
fprintf(logf, "%s %s%s\n", pfx, name, de->d_name);
|
||||
if (verbose > 1) {
|
||||
fprintf(stderr,"%s %s%s\n", pfx, name, de->d_name);
|
||||
fprintf(stderr, "%s %s%s\n", pfx, name, de->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,31 +143,31 @@ Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
if (de->d_type == DT_DIR) {
|
||||
char *p = alloca(strlen(name)+strlen(de->d_name)+2);
|
||||
|
||||
strcpy(p,name); strcat(p,de->d_name); strcat(p, "/");
|
||||
DoDir(dir1,dir2,p);
|
||||
strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
|
||||
DoDir(dir1, dir2, p);
|
||||
s_same_dirs++;
|
||||
} else {
|
||||
char *buf1 = alloca(strlen(dir1) + strlen(name) +
|
||||
strlen(de->d_name) + 3);
|
||||
char *buf2 = alloca(strlen(dir2) + strlen(name) +
|
||||
strlen(de->d_name) + 3);
|
||||
char *m1,md5_1[33],*m2, md5_2[33];
|
||||
u_char *p1,*p2;
|
||||
int fd1,fd2;
|
||||
struct stat s1,s2;
|
||||
char *m1, md5_1[33], *m2, md5_2[33];
|
||||
u_char *p1, *p2;
|
||||
int fd1, fd2;
|
||||
struct stat s1, s2;
|
||||
|
||||
strcpy(buf1,dir1);
|
||||
strcat(buf1,"/"); strcat(buf1,name);
|
||||
strcat(buf1,"/"); strcat(buf1,de->d_name);
|
||||
fd1 = open(buf1,O_RDONLY);
|
||||
strcpy(buf1, dir1);
|
||||
strcat(buf1, "/"); strcat(buf1, name);
|
||||
strcat(buf1, "/"); strcat(buf1, de->d_name);
|
||||
fd1 = open(buf1, O_RDONLY);
|
||||
if(fd1 < 0) { perror(buf1); exit(3); }
|
||||
fstat(fd1,&s1);
|
||||
strcpy(buf2,dir2);
|
||||
strcat(buf2,"/"); strcat(buf2,name);
|
||||
strcat(buf2,"/"); strcat(buf2,de->d_name);
|
||||
fd2 = open(buf2,O_RDONLY);
|
||||
fstat(fd1, &s1);
|
||||
strcpy(buf2, dir2);
|
||||
strcat(buf2, "/"); strcat(buf2, name);
|
||||
strcat(buf2, "/"); strcat(buf2, de->d_name);
|
||||
fd2 = open(buf2, O_RDONLY);
|
||||
if(fd2 < 0) { perror(buf2); exit(3); }
|
||||
fstat(fd2,&s2);
|
||||
fstat(fd2, &s2);
|
||||
#if 0
|
||||
/* XXX if we could just trust the size to change... */
|
||||
if (s1.st_size == s2.st_size) {
|
||||
|
@ -182,23 +178,22 @@ Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
goto finish;
|
||||
}
|
||||
#endif
|
||||
p1=mmap(0,s1.st_size,PROT_READ,MAP_PRIVATE,fd1,0);
|
||||
p1=mmap(0, s1.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
|
||||
if ((int)p1 == -1) { perror(buf1); exit(3); }
|
||||
close(fd1);
|
||||
|
||||
p2=mmap(0,s2.st_size,PROT_READ,MAP_PRIVATE,fd2,0);
|
||||
p2=mmap(0, s2.st_size, PROT_READ, MAP_PRIVATE, fd2, 0);
|
||||
if ((int)p2 == -1) { perror(buf2); exit(3); }
|
||||
close(fd2);
|
||||
|
||||
/* If identical, we're done. */
|
||||
if((s1.st_size == s2.st_size) && !memcmp(p1,p2,s1.st_size)) {
|
||||
if((s1.st_size == s2.st_size) && !memcmp(p1, p2, s1.st_size)) {
|
||||
s_same_files++;
|
||||
s_same_bytes += s1.st_size;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
s_files_chg++;
|
||||
damage++;
|
||||
change++;
|
||||
if (s1.st_size > s2.st_size)
|
||||
s_bytes_del += (s1.st_size - s2.st_size);
|
||||
|
@ -209,11 +204,11 @@ Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
m2 = MD5Data(p2, s2.st_size, md5_2);
|
||||
|
||||
/* Just a curiosity... */
|
||||
if(!strcmp(m1,m2)) {
|
||||
if(!strcmp(m1, m2)) {
|
||||
if (s1.st_size != s2.st_size)
|
||||
fprintf(stderr,
|
||||
"Notice: MD5 same for files of diffent size:\n\t%s\n\t%s\n",
|
||||
buf1,buf2);
|
||||
buf1, buf2);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
|
@ -262,7 +257,7 @@ Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
strcat(cmd, buf1);
|
||||
strcat(cmd, " ");
|
||||
strcat(cmd, buf2);
|
||||
F = popen(cmd,"r");
|
||||
F = popen(cmd, "r");
|
||||
for (j = 1, l = 0; l < s2.st_size; ) {
|
||||
j = fread(ob+l, 1, s2.st_size - l, F);
|
||||
if (j < 1)
|
||||
|
@ -278,26 +273,26 @@ Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
pclose(F);
|
||||
|
||||
if (l && l < s2.st_size) {
|
||||
name_stat("CTMFN",dir2,name,de);
|
||||
printf(" %s %s %d\n",m1,m2,(unsigned)l);
|
||||
fwrite(ob,1,l,stdout);
|
||||
name_stat("CTMFN", dir2, name, de);
|
||||
printf(" %s %s %d\n", m1, m2, (unsigned)l);
|
||||
fwrite(ob, 1, l, stdout);
|
||||
putchar('\n');
|
||||
s_edit_files++;
|
||||
s_edit_bytes += l;
|
||||
s_edit_saves += (s2.st_size - l);
|
||||
} else {
|
||||
subst:
|
||||
name_stat("CTMFS",dir2,name,de);
|
||||
printf(" %s %s %u\n",m1,m2,(unsigned)s2.st_size);
|
||||
fwrite(p2,1,s2.st_size,stdout);
|
||||
name_stat("CTMFS", dir2, name, de);
|
||||
printf(" %s %s %u\n", m1, m2, (unsigned)s2.st_size);
|
||||
fwrite(p2, 1, s2.st_size, stdout);
|
||||
putchar('\n');
|
||||
s_sub_files++;
|
||||
s_sub_bytes += s2.st_size;
|
||||
}
|
||||
}
|
||||
finish:
|
||||
munmap(p1,s1.st_size);
|
||||
munmap(p2,s2.st_size);
|
||||
munmap(p1, s1.st_size);
|
||||
munmap(p2, s2.st_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,11 +302,11 @@ Add(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
change++;
|
||||
if (de->d_type == DT_DIR) {
|
||||
char *p = alloca(strlen(name)+strlen(de->d_name)+2);
|
||||
strcpy(p,name); strcat(p,de->d_name); strcat(p, "/");
|
||||
name_stat("CTMDM",dir2,name,de);
|
||||
strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
|
||||
name_stat("CTMDM", dir2, name, de);
|
||||
putchar('\n');
|
||||
s_new_dirs++;
|
||||
DoDir(dir1,dir2,p);
|
||||
DoDir(dir1, dir2, p);
|
||||
} else if (de->d_type == DT_REG) {
|
||||
char *buf2 = alloca(strlen(dir2) + strlen(name) +
|
||||
strlen(de->d_name) + 3);
|
||||
|
@ -320,21 +315,21 @@ Add(const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
struct stat st;
|
||||
int fd1;
|
||||
|
||||
strcpy(buf2,dir2);
|
||||
strcat(buf2,"/"); strcat(buf2,name);
|
||||
strcat(buf2,"/"); strcat(buf2,de->d_name);
|
||||
fd1 = open(buf2,O_RDONLY);
|
||||
strcpy(buf2, dir2);
|
||||
strcat(buf2, "/"); strcat(buf2, name);
|
||||
strcat(buf2, "/"); strcat(buf2, de->d_name);
|
||||
fd1 = open(buf2, O_RDONLY);
|
||||
if (fd1 < 0) {perror(buf2); exit (3); }
|
||||
fstat(fd1,&st);
|
||||
p1=mmap(0,st.st_size,PROT_READ,MAP_PRIVATE,fd1,0);
|
||||
fstat(fd1, &st);
|
||||
p1=mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd1, 0);
|
||||
if ((int)p1 == -1) { perror(buf2); exit(3); }
|
||||
close(fd1);
|
||||
m2 = MD5Data(p1, st.st_size, md5_2);
|
||||
name_stat("CTMFM",dir2,name,de);
|
||||
printf(" %s %u\n",m2,(unsigned)st.st_size);
|
||||
fwrite(p1,1,st.st_size,stdout);
|
||||
name_stat("CTMFM", dir2, name, de);
|
||||
printf(" %s %u\n", m2, (unsigned)st.st_size);
|
||||
fwrite(p1, 1, st.st_size, stdout);
|
||||
putchar('\n');
|
||||
munmap(p1,st.st_size);
|
||||
munmap(p1, st.st_size);
|
||||
s_new_files++;
|
||||
s_new_bytes += st.st_size;
|
||||
}
|
||||
|
@ -347,19 +342,27 @@ Del (const char *dir1, const char *dir2, const char *name, struct dirent *de)
|
|||
change++;
|
||||
if (de->d_type == DT_DIR) {
|
||||
char *p = alloca(strlen(name)+strlen(de->d_name)+2);
|
||||
strcpy(p,name); strcat(p,de->d_name); strcat(p, "/");
|
||||
DoDir(dir1,dir2,p);
|
||||
printf("CTMDR %s%s\n",name,de->d_name);
|
||||
strcpy(p, name); strcat(p, de->d_name); strcat(p, "/");
|
||||
DoDir(dir1, dir2, p);
|
||||
printf("CTMDR %s%s\n", name, de->d_name);
|
||||
fprintf(logf, "CTMDR %s%s\n", name, de->d_name);
|
||||
if (verbose > 1) {
|
||||
fprintf(stderr, "CTMDR %s%s\n", name, de->d_name);
|
||||
}
|
||||
s_del_dirs++;
|
||||
} else if (de->d_type == DT_REG) {
|
||||
char *buf1 = alloca(strlen(dir1) + strlen(name) +
|
||||
strlen(de->d_name) + 3);
|
||||
char *m1, md5_1[33];
|
||||
strcpy(buf1,dir1);
|
||||
strcat(buf1,"/"); strcat(buf1,name);
|
||||
strcat(buf1,"/"); strcat(buf1,de->d_name);
|
||||
strcpy(buf1, dir1);
|
||||
strcat(buf1, "/"); strcat(buf1, name);
|
||||
strcat(buf1, "/"); strcat(buf1, de->d_name);
|
||||
m1 = MD5File(buf1, md5_1);
|
||||
printf("CTMFR %s%s %s\n",name,de->d_name,m1);
|
||||
printf("CTMFR %s%s %s\n", name, de->d_name, m1);
|
||||
fprintf(logf, "CTMFR %s%s %s\n", name, de->d_name, m1);
|
||||
if (verbose > 1) {
|
||||
fprintf(stderr, "CTMFR %s%s\n", name, de->d_name);
|
||||
}
|
||||
s_del_files++;
|
||||
s_del_bytes += StatFile(buf1)->st_size;
|
||||
}
|
||||
|
@ -377,26 +380,27 @@ GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u
|
|||
return;
|
||||
*buf = 0;
|
||||
if (*dir != '/')
|
||||
strcat(buf,"/");
|
||||
strcat(buf,dir);
|
||||
strcat(buf, "/");
|
||||
strcat(buf, dir);
|
||||
if (buf[strlen(buf)-1] != '/')
|
||||
strcat(buf,"/");
|
||||
strcat(buf,name);
|
||||
strcat(buf, "/");
|
||||
strcat(buf, name);
|
||||
if (buf[strlen(buf)-1] != '/')
|
||||
strcat(buf,"/");
|
||||
strcat(buf,nl[*i]->d_name);
|
||||
strcat(buf, "/");
|
||||
strcat(buf, nl[*i]->d_name);
|
||||
if (flag_ignore &&
|
||||
!regexec(®_ignore,buf,0,0,0)) {
|
||||
!regexec(®_ignore, buf, 0, 0, 0)) {
|
||||
(*ignored)++;
|
||||
fprintf(logf, "Ignore %s\n", buf);
|
||||
if (verbose > 2) {
|
||||
fprintf(stderr,"Ignore %s\n",buf);
|
||||
fprintf(stderr, "Ignore %s\n", buf);
|
||||
}
|
||||
} else if (flag_bogus &&
|
||||
!regexec(®_bogus,buf,0,0,0)) {
|
||||
!regexec(®_bogus, buf, 0, 0, 0)) {
|
||||
(*bogus)++;
|
||||
if (verbose > 0) {
|
||||
fprintf(stderr,"Bogus %s\n",buf);
|
||||
}
|
||||
fprintf(logf, "Bogus %s\n", buf);
|
||||
fprintf(stderr, "Bogus %s\n", buf);
|
||||
damage++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -409,7 +413,7 @@ GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u
|
|||
break;
|
||||
(*wrong)++;
|
||||
if (verbose > 0)
|
||||
fprintf(stderr,"Wrong %s\n",buf);
|
||||
fprintf(stderr, "Wrong %s\n", buf);
|
||||
free(nl[*i]); nl[*i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -417,13 +421,13 @@ GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u
|
|||
void
|
||||
DoDir(const char *dir1, const char *dir2, const char *name)
|
||||
{
|
||||
int i1,i2,n1,n2,i;
|
||||
struct dirent **nl1,**nl2;
|
||||
int i1, i2, n1, n2, i;
|
||||
struct dirent **nl1, **nl2;
|
||||
char *buf1 = alloca(strlen(dir1) + strlen(name) + 4);
|
||||
char *buf2 = alloca(strlen(dir2) + strlen(name) + 4);
|
||||
|
||||
strcpy(buf1,dir1); strcat(buf1,"/"); strcat(buf1,name);
|
||||
strcpy(buf2,dir2); strcat(buf2,"/"); strcat(buf2,name);
|
||||
strcpy(buf1, dir1); strcat(buf1, "/"); strcat(buf1, name);
|
||||
strcpy(buf2, dir2); strcat(buf2, "/"); strcat(buf2, name);
|
||||
n1 = scandir(buf1, &nl1, dirselect, alphasort);
|
||||
n2 = scandir(buf2, &nl2, dirselect, alphasort);
|
||||
i1 = i2 = -1;
|
||||
|
@ -449,31 +453,31 @@ DoDir(const char *dir1, const char *dir2, const char *name)
|
|||
break;
|
||||
} else if (i1 >= n1 && i2 < n2) {
|
||||
/* end of list 1, add anything left on list 2 */
|
||||
Add(dir1,dir2,name,nl2[i2]);
|
||||
Add(dir1, dir2, name, nl2[i2]);
|
||||
free(nl2[i2]); nl2[i2] = 0;
|
||||
} else if (i1 < n1 && i2 >= n2) {
|
||||
/* end of list 2, delete anything left on list 1 */
|
||||
Del(dir1,dir2,name,nl1[i1]);
|
||||
Del(dir1, dir2, name, nl1[i1]);
|
||||
free(nl1[i1]); nl1[i1] = 0;
|
||||
} else if (!(i = strcmp(nl1[i1]->d_name, nl2[i2]->d_name))) {
|
||||
/* Identical names */
|
||||
if (nl1[i1]->d_type == nl2[i2]->d_type) {
|
||||
/* same type */
|
||||
Equ(dir1,dir2,name,nl1[i1]);
|
||||
Equ(dir1, dir2, name, nl1[i1]);
|
||||
} else {
|
||||
/* different types */
|
||||
Del(dir1,dir2,name,nl1[i1]);
|
||||
Add(dir1,dir2,name,nl2[i2]);
|
||||
Del(dir1, dir2, name, nl1[i1]);
|
||||
Add(dir1, dir2, name, nl2[i2]);
|
||||
}
|
||||
free(nl1[i1]); nl1[i1] = 0;
|
||||
free(nl2[i2]); nl2[i2] = 0;
|
||||
} else if (i < 0) {
|
||||
/* Something extra in list 1, delete it */
|
||||
Del(dir1,dir2,name,nl1[i1]);
|
||||
Del(dir1, dir2, name, nl1[i1]);
|
||||
free(nl1[i1]); nl1[i1] = 0;
|
||||
} else {
|
||||
/* Something extra in list 2, add it */
|
||||
Add(dir1,dir2,name,nl2[i2]);
|
||||
Add(dir1, dir2, name, nl2[i2]);
|
||||
free(nl2[i2]); nl2[i2] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -492,22 +496,24 @@ main(int argc, char **argv)
|
|||
|
||||
setbuf(stderr, NULL);
|
||||
|
||||
if (regcomp(®_bogus,DEFAULT_BOGUS, REG_EXTENDED | REG_NEWLINE))
|
||||
#if 0
|
||||
if (regcomp(®_bogus, DEFAULT_BOGUS, REG_EXTENDED | REG_NEWLINE))
|
||||
/* XXX use regerror to explain it */
|
||||
err(1,"Default regular expression argument to -B is botched");
|
||||
errx(1, "Default regular expression argument to -B is botched");
|
||||
flag_bogus = 1;
|
||||
|
||||
if (regcomp(®_ignore,DEFAULT_IGNORE, REG_EXTENDED | REG_NEWLINE))
|
||||
if (regcomp(®_ignore, DEFAULT_IGNORE, REG_EXTENDED | REG_NEWLINE))
|
||||
/* XXX use regerror to explain it */
|
||||
err(1,"Default regular expression argument to -I is botched");
|
||||
errx(1, "Default regular expression argument to -I is botched");
|
||||
flag_ignore = 1;
|
||||
#endif
|
||||
|
||||
while ((i = getopt(argc,argv,"D:I:B:qv")) != EOF)
|
||||
while ((i = getopt(argc, argv, "D:I:B:l:qv")) != EOF)
|
||||
switch (i) {
|
||||
case 'D':
|
||||
damage_limit = strtol(optarg,0,0);
|
||||
damage_limit = strtol(optarg, 0, 0);
|
||||
if (damage_limit < 0)
|
||||
err(1,"Damage limit must be positive");
|
||||
errx(1, "Damage limit must be positive");
|
||||
break;
|
||||
case 'I':
|
||||
if (flag_ignore)
|
||||
|
@ -515,10 +521,10 @@ main(int argc, char **argv)
|
|||
flag_ignore = 0;
|
||||
if (!*optarg)
|
||||
break;
|
||||
if (regcomp(®_ignore,optarg,
|
||||
if (regcomp(®_ignore, optarg,
|
||||
REG_EXTENDED | REG_NEWLINE))
|
||||
/* XXX use regerror to explain it */
|
||||
err(1,"Regular expression argument to -I is botched");
|
||||
errx(1, "Regular expression argument to -I is botched");
|
||||
flag_ignore = 1;
|
||||
break;
|
||||
case 'B':
|
||||
|
@ -527,12 +533,17 @@ main(int argc, char **argv)
|
|||
flag_bogus = 0;
|
||||
if (!*optarg)
|
||||
break;
|
||||
if (regcomp(®_bogus,optarg,
|
||||
if (regcomp(®_bogus, optarg,
|
||||
REG_EXTENDED | REG_NEWLINE))
|
||||
/* XXX use regerror to explain it */
|
||||
err(1,"Regular expression argument to -B is botched");
|
||||
errx(1, "Regular expression argument to -B is botched");
|
||||
flag_bogus = 1;
|
||||
break;
|
||||
case 'l':
|
||||
logf = fopen(optarg, "w");
|
||||
if (!logf)
|
||||
err(1, optarg);
|
||||
break;
|
||||
case 'q':
|
||||
verbose--;
|
||||
break;
|
||||
|
@ -547,26 +558,35 @@ main(int argc, char **argv)
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
setbuf(stdout,0);
|
||||
if (!logf)
|
||||
logf = fopen("/dev/null", "w");
|
||||
|
||||
setbuf(stdout, 0);
|
||||
|
||||
if (argc != 6) {
|
||||
Usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
signal(SIGINFO,stat_info);
|
||||
signal(SIGINFO, stat_info);
|
||||
|
||||
fprintf(stderr, "CTM_BEGIN 2.0 %s %s %s %s\n",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
fprintf(logf, "CTM_BEGIN 2.0 %s %s %s %s\n",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
printf("CTM_BEGIN 2.0 %s %s %s %s\n",
|
||||
argv[0], argv[1], argv[2], argv[3]);
|
||||
DoDir(argv[4],argv[5],"");
|
||||
DoDir(argv[4], argv[5], "");
|
||||
if (damage_limit && damage > damage_limit) {
|
||||
print_stat(stderr,"");
|
||||
err(1,"Damage would exceede %d files", damage_limit);
|
||||
} else if (!change) {
|
||||
err(1,"No changes");
|
||||
print_stat(stderr, "DAMAGE: ");
|
||||
errx(1, "Damage of %d would exceed %d files",
|
||||
damage, damage_limit);
|
||||
} else if (change < 2) {
|
||||
errx(1, "No changes");
|
||||
} else {
|
||||
printf("CTM_END ");
|
||||
print_stat(stderr,"");
|
||||
fprintf(logf, "CTM_END\n");
|
||||
print_stat(stderr, "END: ");
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue