1/* Still missing: 2 * 3 * Damage counter 4 * Change counter 5 * Time stamp 6 * prefix 7 * cmd-line args 8 * %100 deltas 9 * delta and Add are different. delta -> Equ. 10 * 11 * mkctm 12 * -B regex Bogus 13 * -I regex Ignore
| 1/* Still missing: 2 * 3 * Damage counter 4 * Change counter 5 * Time stamp 6 * prefix 7 * cmd-line args 8 * %100 deltas 9 * delta and Add are different. delta -> Equ. 10 * 11 * mkctm 12 * -B regex Bogus 13 * -I regex Ignore
|
14 * -D int Damage
| 14 * -D int Damage 15 * -q decrease verbosity
|
15 * -v increase verbosity
| 16 * -v increase verbosity
|
16 * -l str control logging.
| 17 * (-l str control logging.)
|
17 * name cvs-cur 18 * prefix src/secure 19 * dir1 "Soll" 20 * dir2 "Ist" 21 * 22 */ 23 24#include <sys/types.h> 25#include <sys/stat.h> 26#include <sys/mman.h> 27#include <sys/wait.h> 28#include <dirent.h> 29#include <regex.h> 30#include <stdio.h> 31#include <fcntl.h> 32#include <string.h> 33#include <stdlib.h> 34#include <unistd.h> 35#include <md5.h> 36#include <err.h> 37#include <signal.h> 38
| 18 * name cvs-cur 19 * prefix src/secure 20 * dir1 "Soll" 21 * dir2 "Ist" 22 * 23 */ 24 25#include <sys/types.h> 26#include <sys/stat.h> 27#include <sys/mman.h> 28#include <sys/wait.h> 29#include <dirent.h> 30#include <regex.h> 31#include <stdio.h> 32#include <fcntl.h> 33#include <string.h> 34#include <stdlib.h> 35#include <unistd.h> 36#include <md5.h> 37#include <err.h> 38#include <signal.h> 39
|
39#define DEFAULT_IGNORE "/CVS$|/\\.#" 40#define DEFAULT_BOGUS "\\.core$"
| 40#define DEFAULT_IGNORE "/CVS$|/\\.#|00_TRANS\\.TBL$" 41#define DEFAULT_BOGUS "\\.core$|\\.orig$|\\.rej$"
|
41regex_t reg_ignore, reg_bogus; 42int flag_ignore, flag_bogus; 43
| 42regex_t reg_ignore, reg_bogus; 43int flag_ignore, flag_bogus; 44
|
| 45int verbose; 46int damage, damage_limit; 47int change; 48
|
44u_long s1_ignored, s2_ignored; 45u_long s1_bogus, s2_bogus; 46u_long s1_wrong, s2_wrong;
| 49u_long s1_ignored, s2_ignored; 50u_long s1_bogus, s2_bogus; 51u_long s1_wrong, s2_wrong;
|
47u_long s_same_dirs, s_same_files, s_same_bytes; 48u_long s_files_chg, s_bytes_add, s_bytes_del;
| |
49u_long s_new_dirs, s_new_files, s_new_bytes;
| 52u_long s_new_dirs, s_new_files, s_new_bytes;
|
50u_long s_del_dirs, s_del_files, s_del_bytes; 51u_long s_chg_files, s_chg_bytes;
| 53u_long s_del_dirs, s_del_files, s_del_bytes; 54u_long s_files_chg, s_bytes_add, s_bytes_del; 55u_long s_same_dirs, s_same_files, s_same_bytes;
|
52u_long s_edit_files, s_edit_bytes, s_edit_saves; 53u_long s_sub_files, s_sub_bytes; 54 55void
| 56u_long s_edit_files, s_edit_bytes, s_edit_saves; 57u_long s_sub_files, s_sub_bytes; 58 59void
|
| 60Usage(void) 61{ 62 fprintf(stderr, "Usage:\n"); 63 fprintf(stderr, "\tmkctm [-options] name number timestamp prefix"); 64 fprintf(stderr, " dir1 dir2"); 65 fprintf(stderr, "Options:\n"); 66 fprintf(stderr, "\t\t-B bogus_regexp\n"); 67 fprintf(stderr, "\t\t-D damage_limit\n"); 68 fprintf(stderr, "\t\t-I ignore_regexp\n"); 69 fprintf(stderr, "\t\t-q\n"); 70 fprintf(stderr, "\t\t-v\n"); 71} 72 73void
|
56print_stat(FILE *fd, char *pre) 57{ 58 fprintf(fd,"%sAvoided:\n",pre); 59 fprintf(fd,"%s ignore: %5lu old %5lu new\n", 60 pre, s1_ignored, s2_ignored); 61 fprintf(fd,"%s bogus: %5lu old %5lu new\n", 62 pre, s1_bogus, s2_bogus); 63 fprintf(fd,"%s wrong: %5lu old %5lu new\n", 64 pre, s1_wrong, s2_wrong); 65 fprintf(fd,"%sDelta:\n",pre); 66 fprintf(fd,"%s new: %5lu dirs %5lu files %9lu plus\n", 67 pre, s_new_dirs, s_new_files, s_new_bytes); 68 fprintf(fd,"%s del: %5lu dirs %5lu files %9lu minus\n", 69 pre, s_del_dirs, s_del_files, s_del_bytes); 70 fprintf(fd,"%s chg: %5lu files %9lu plus %9lu minus\n", 71 pre, s_files_chg, s_bytes_add, s_bytes_del); 72 fprintf(fd,"%s same: %5lu dirs %5lu files %9lu bytes\n", 73 pre, s_same_dirs, s_same_files, s_same_bytes); 74 fprintf(fd,"%sMethod:\n",pre); 75 fprintf(fd,"%s edit: %5lu files %9lu bytes %9lu saved\n", 76 pre, s_edit_files, s_edit_bytes, s_edit_saves); 77 fprintf(fd,"%s sub: %5lu files %9lu bytes\n", 78 pre, s_sub_files, s_sub_bytes); 79} 80 81void 82stat_info(int foo) 83{ 84 signal(SIGINFO,stat_info); 85 print_stat(stderr,"INFO: "); 86} 87 88void DoDir(const char *dir1, const char *dir2, const char *name); 89 90static struct stat st; 91static __inline struct stat * 92StatFile(char *name) 93{ 94 if (lstat(name,&st) < 0) 95 err(1,"Couldn't stat %s\n",name); 96 return &st; 97} 98 99int 100dirselect(struct dirent *de) 101{ 102 if (!strcmp(de->d_name,".")) return 0; 103 if (!strcmp(de->d_name,"..")) return 0; 104 return 1; 105} 106 107void 108name_stat(const char *pfx, const char *dir, const char *name, struct dirent *de) 109{ 110 char *buf = alloca(strlen(dir) + strlen(name) + 111 strlen(de->d_name) + 3); 112 struct stat *st; 113 114 strcpy(buf,dir); 115 strcat(buf,"/"); strcat(buf,name); 116 strcat(buf,"/"); strcat(buf,de->d_name); 117 st = StatFile(buf); 118 printf("%s %s%s %lu %lu %o", 119 pfx, name, de->d_name, 120 st->st_uid, st->st_gid, st->st_mode & ~S_IFMT);
| 74print_stat(FILE *fd, char *pre) 75{ 76 fprintf(fd,"%sAvoided:\n",pre); 77 fprintf(fd,"%s ignore: %5lu old %5lu new\n", 78 pre, s1_ignored, s2_ignored); 79 fprintf(fd,"%s bogus: %5lu old %5lu new\n", 80 pre, s1_bogus, s2_bogus); 81 fprintf(fd,"%s wrong: %5lu old %5lu new\n", 82 pre, s1_wrong, s2_wrong); 83 fprintf(fd,"%sDelta:\n",pre); 84 fprintf(fd,"%s new: %5lu dirs %5lu files %9lu plus\n", 85 pre, s_new_dirs, s_new_files, s_new_bytes); 86 fprintf(fd,"%s del: %5lu dirs %5lu files %9lu minus\n", 87 pre, s_del_dirs, s_del_files, s_del_bytes); 88 fprintf(fd,"%s chg: %5lu files %9lu plus %9lu minus\n", 89 pre, s_files_chg, s_bytes_add, s_bytes_del); 90 fprintf(fd,"%s same: %5lu dirs %5lu files %9lu bytes\n", 91 pre, s_same_dirs, s_same_files, s_same_bytes); 92 fprintf(fd,"%sMethod:\n",pre); 93 fprintf(fd,"%s edit: %5lu files %9lu bytes %9lu saved\n", 94 pre, s_edit_files, s_edit_bytes, s_edit_saves); 95 fprintf(fd,"%s sub: %5lu files %9lu bytes\n", 96 pre, s_sub_files, s_sub_bytes); 97} 98 99void 100stat_info(int foo) 101{ 102 signal(SIGINFO,stat_info); 103 print_stat(stderr,"INFO: "); 104} 105 106void DoDir(const char *dir1, const char *dir2, const char *name); 107 108static struct stat st; 109static __inline struct stat * 110StatFile(char *name) 111{ 112 if (lstat(name,&st) < 0) 113 err(1,"Couldn't stat %s\n",name); 114 return &st; 115} 116 117int 118dirselect(struct dirent *de) 119{ 120 if (!strcmp(de->d_name,".")) return 0; 121 if (!strcmp(de->d_name,"..")) return 0; 122 return 1; 123} 124 125void 126name_stat(const char *pfx, const char *dir, const char *name, struct dirent *de) 127{ 128 char *buf = alloca(strlen(dir) + strlen(name) + 129 strlen(de->d_name) + 3); 130 struct stat *st; 131 132 strcpy(buf,dir); 133 strcat(buf,"/"); strcat(buf,name); 134 strcat(buf,"/"); strcat(buf,de->d_name); 135 st = StatFile(buf); 136 printf("%s %s%s %lu %lu %o", 137 pfx, name, de->d_name, 138 st->st_uid, st->st_gid, st->st_mode & ~S_IFMT);
|
| 139 if (verbose > 1) { 140 fprintf(stderr,"%s %s%s\n", pfx, name, de->d_name); 141 }
|
121} 122 123void 124Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de) 125{ 126 if (de->d_type == DT_DIR) { 127 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 128 129 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 130 DoDir(dir1,dir2,p); 131 s_same_dirs++; 132 } else { 133 char *buf1 = alloca(strlen(dir1) + strlen(name) + 134 strlen(de->d_name) + 3); 135 char *buf2 = alloca(strlen(dir2) + strlen(name) + 136 strlen(de->d_name) + 3); 137 char *m1,md5_1[33],*m2, md5_2[33];
| 142} 143 144void 145Equ(const char *dir1, const char *dir2, const char *name, struct dirent *de) 146{ 147 if (de->d_type == DT_DIR) { 148 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 149 150 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 151 DoDir(dir1,dir2,p); 152 s_same_dirs++; 153 } else { 154 char *buf1 = alloca(strlen(dir1) + strlen(name) + 155 strlen(de->d_name) + 3); 156 char *buf2 = alloca(strlen(dir2) + strlen(name) + 157 strlen(de->d_name) + 3); 158 char *m1,md5_1[33],*m2, md5_2[33];
|
138 void *p1,*p2;
| 159 u_char *p1,*p2;
|
139 int fd1,fd2; 140 struct stat s1,s2; 141 142 strcpy(buf1,dir1); 143 strcat(buf1,"/"); strcat(buf1,name); 144 strcat(buf1,"/"); strcat(buf1,de->d_name); 145 fd1 = open(buf1,O_RDONLY); 146 if(fd1 < 0) { perror(buf1); exit(3); } 147 fstat(fd1,&s1); 148 strcpy(buf2,dir2); 149 strcat(buf2,"/"); strcat(buf2,name); 150 strcat(buf2,"/"); strcat(buf2,de->d_name); 151 fd2 = open(buf2,O_RDONLY); 152 if(fd2 < 0) { perror(buf2); exit(3); } 153 fstat(fd2,&s2);
| 160 int fd1,fd2; 161 struct stat s1,s2; 162 163 strcpy(buf1,dir1); 164 strcat(buf1,"/"); strcat(buf1,name); 165 strcat(buf1,"/"); strcat(buf1,de->d_name); 166 fd1 = open(buf1,O_RDONLY); 167 if(fd1 < 0) { perror(buf1); exit(3); } 168 fstat(fd1,&s1); 169 strcpy(buf2,dir2); 170 strcat(buf2,"/"); strcat(buf2,name); 171 strcat(buf2,"/"); strcat(buf2,de->d_name); 172 fd2 = open(buf2,O_RDONLY); 173 if(fd2 < 0) { perror(buf2); exit(3); } 174 fstat(fd2,&s2);
|
154#if 1
| 175#if 0 176 /* XXX if we could just trust the size to change... */
|
155 if (s1.st_size == s2.st_size) { 156 s_same_files++; 157 s_same_bytes += s1.st_size; 158 close(fd1); 159 close(fd2); 160 goto finish; 161 } 162#endif 163 p1=mmap(0,s1.st_size,PROT_READ,MAP_PRIVATE,fd1,0); 164 if ((int)p1 == -1) { perror(buf1); exit(3); } 165 close(fd1); 166 167 p2=mmap(0,s2.st_size,PROT_READ,MAP_PRIVATE,fd2,0); 168 if ((int)p2 == -1) { perror(buf2); exit(3); } 169 close(fd2); 170 171 /* If identical, we're done. */ 172 if((s1.st_size == s2.st_size) && !memcmp(p1,p2,s1.st_size)) { 173 s_same_files++; 174 s_same_bytes += s1.st_size; 175 goto finish; 176 } 177 178 s_files_chg++;
| 177 if (s1.st_size == s2.st_size) { 178 s_same_files++; 179 s_same_bytes += s1.st_size; 180 close(fd1); 181 close(fd2); 182 goto finish; 183 } 184#endif 185 p1=mmap(0,s1.st_size,PROT_READ,MAP_PRIVATE,fd1,0); 186 if ((int)p1 == -1) { perror(buf1); exit(3); } 187 close(fd1); 188 189 p2=mmap(0,s2.st_size,PROT_READ,MAP_PRIVATE,fd2,0); 190 if ((int)p2 == -1) { perror(buf2); exit(3); } 191 close(fd2); 192 193 /* If identical, we're done. */ 194 if((s1.st_size == s2.st_size) && !memcmp(p1,p2,s1.st_size)) { 195 s_same_files++; 196 s_same_bytes += s1.st_size; 197 goto finish; 198 } 199 200 s_files_chg++;
|
| 201 damage++; 202 change++;
|
179 if (s1.st_size > s2.st_size) 180 s_bytes_del += (s1.st_size - s2.st_size); 181 else 182 s_bytes_add += (s2.st_size - s1.st_size); 183 184 m1 = MD5Data(p1, s1.st_size, md5_1); 185 m2 = MD5Data(p2, s2.st_size, md5_2); 186 187 /* Just a curiosity... */ 188 if(!strcmp(m1,m2)) { 189 if (s1.st_size != s2.st_size) 190 fprintf(stderr, 191 "Notice: MD5 same for files of diffent size:\n\t%s\n\t%s\n", 192 buf1,buf2); 193 goto finish; 194 } 195 196 {
| 203 if (s1.st_size > s2.st_size) 204 s_bytes_del += (s1.st_size - s2.st_size); 205 else 206 s_bytes_add += (s2.st_size - s1.st_size); 207 208 m1 = MD5Data(p1, s1.st_size, md5_1); 209 m2 = MD5Data(p2, s2.st_size, md5_2); 210 211 /* Just a curiosity... */ 212 if(!strcmp(m1,m2)) { 213 if (s1.st_size != s2.st_size) 214 fprintf(stderr, 215 "Notice: MD5 same for files of diffent size:\n\t%s\n\t%s\n", 216 buf1,buf2); 217 goto finish; 218 } 219 220 {
|
197 u_long l = s1.st_size + s2.st_size; 198 u_char *ob = alloca(l); 199 Dissect(p1,p1+s1.st_size,p2,p2+s2.st_size,ob,&l);
| 221 u_long l = s2.st_size + 2; 222 u_char *cmd = alloca(strlen(buf1)+strlen(buf2)+100); 223 u_char *ob = alloca(l), *p; 224 int j; 225 FILE *F; 226 227 if (p1[s1.st_size-1] != '\n') { 228 if (verbose > 0) 229 fprintf(stderr, 230 "last char != \\n in %s\n", 231 buf1); 232 goto subst; 233 } 234 235 if (p2[s2.st_size-1] != '\n') { 236 if (verbose > 0) 237 fprintf(stderr, 238 "last char != \\n in %s\n", 239 buf2); 240 goto subst; 241 } 242 243 for (p=p1; p<p1+s1.st_size; p++) 244 if (!*p) { 245 if (verbose > 0) 246 fprintf(stderr, 247 "NULL char in %s\n", 248 buf1); 249 goto subst; 250 } 251 252 for (p=p2; p<p2+s2.st_size; p++) 253 if (!*p) { 254 if (verbose > 0) 255 fprintf(stderr, 256 "NULL char in %s\n", 257 buf2); 258 goto subst; 259 } 260 261 strcpy(cmd, "diff -n "); 262 strcat(cmd, buf1); 263 strcat(cmd, " "); 264 strcat(cmd, buf2); 265 F = popen(cmd,"r"); 266 for (j = 1, l = 0; l < s2.st_size; ) { 267 j = fread(ob+l, 1, s2.st_size - l, F); 268 if (j < 1) 269 break; 270 l += j; 271 continue; 272 } 273 if (j) { 274 l = 0; 275 while (EOF != fgetc(F)) 276 continue; 277 } 278 pclose(F); 279
|
200 if (l && l < s2.st_size) {
| 280 if (l && l < s2.st_size) {
|
201 name_stat("CTMFB",dir2,name,de); 202 printf(" %s %s %d\n",m1,m2,(unsigned)s1.st_size);
| 281 name_stat("CTMFN",dir2,name,de); 282 printf(" %s %s %d\n",m1,m2,(unsigned)l); 283 fwrite(ob,1,l,stdout); 284 putchar('\n');
|
203 s_edit_files++; 204 s_edit_bytes += l; 205 s_edit_saves += (s2.st_size - l);
| 285 s_edit_files++; 286 s_edit_bytes += l; 287 s_edit_saves += (s2.st_size - l);
|
206 fwrite(ob,1,l,stdout); 207 putchar('\n');
| |
208 } else {
| 288 } else {
|
| 289 subst:
|
209 name_stat("CTMFS",dir2,name,de); 210 printf(" %s %s %u\n",m1,m2,(unsigned)s2.st_size); 211 fwrite(p2,1,s2.st_size,stdout);
| 290 name_stat("CTMFS",dir2,name,de); 291 printf(" %s %s %u\n",m1,m2,(unsigned)s2.st_size); 292 fwrite(p2,1,s2.st_size,stdout);
|
| 293 putchar('\n');
|
212 s_sub_files++; 213 s_sub_bytes += s2.st_size; 214 } 215 } 216 finish: 217 munmap(p1,s1.st_size); 218 munmap(p2,s2.st_size); 219 } 220} 221 222void 223Add(const char *dir1, const char *dir2, const char *name, struct dirent *de) 224{
| 294 s_sub_files++; 295 s_sub_bytes += s2.st_size; 296 } 297 } 298 finish: 299 munmap(p1,s1.st_size); 300 munmap(p2,s2.st_size); 301 } 302} 303 304void 305Add(const char *dir1, const char *dir2, const char *name, struct dirent *de) 306{
|
| 307 change++;
|
225 if (de->d_type == DT_DIR) { 226 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 227 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 228 name_stat("CTMDM",dir2,name,de); 229 putchar('\n'); 230 s_new_dirs++; 231 DoDir(dir1,dir2,p); 232 } else if (de->d_type == DT_REG) { 233 char *buf2 = alloca(strlen(dir2) + strlen(name) + 234 strlen(de->d_name) + 3); 235 char *m2, md5_2[33]; 236 u_char *p1; 237 struct stat st; 238 int fd1; 239 240 strcpy(buf2,dir2); 241 strcat(buf2,"/"); strcat(buf2,name); 242 strcat(buf2,"/"); strcat(buf2,de->d_name); 243 fd1 = open(buf2,O_RDONLY); 244 if (fd1 < 0) {perror(buf2); exit (3); } 245 fstat(fd1,&st); 246 p1=mmap(0,st.st_size,PROT_READ,MAP_PRIVATE,fd1,0); 247 if ((int)p1 == -1) { perror(buf2); exit(3); } 248 close(fd1); 249 m2 = MD5Data(p1, st.st_size, md5_2); 250 name_stat("CTMFM",dir2,name,de); 251 printf(" %s %u\n",m2,(unsigned)st.st_size); 252 fwrite(p1,1,st.st_size,stdout); 253 putchar('\n'); 254 munmap(p1,st.st_size); 255 s_new_files++; 256 s_new_bytes += st.st_size; 257 } 258} 259 260void 261Del (const char *dir1, const char *dir2, const char *name, struct dirent *de) 262{
| 308 if (de->d_type == DT_DIR) { 309 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 310 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 311 name_stat("CTMDM",dir2,name,de); 312 putchar('\n'); 313 s_new_dirs++; 314 DoDir(dir1,dir2,p); 315 } else if (de->d_type == DT_REG) { 316 char *buf2 = alloca(strlen(dir2) + strlen(name) + 317 strlen(de->d_name) + 3); 318 char *m2, md5_2[33]; 319 u_char *p1; 320 struct stat st; 321 int fd1; 322 323 strcpy(buf2,dir2); 324 strcat(buf2,"/"); strcat(buf2,name); 325 strcat(buf2,"/"); strcat(buf2,de->d_name); 326 fd1 = open(buf2,O_RDONLY); 327 if (fd1 < 0) {perror(buf2); exit (3); } 328 fstat(fd1,&st); 329 p1=mmap(0,st.st_size,PROT_READ,MAP_PRIVATE,fd1,0); 330 if ((int)p1 == -1) { perror(buf2); exit(3); } 331 close(fd1); 332 m2 = MD5Data(p1, st.st_size, md5_2); 333 name_stat("CTMFM",dir2,name,de); 334 printf(" %s %u\n",m2,(unsigned)st.st_size); 335 fwrite(p1,1,st.st_size,stdout); 336 putchar('\n'); 337 munmap(p1,st.st_size); 338 s_new_files++; 339 s_new_bytes += st.st_size; 340 } 341} 342 343void 344Del (const char *dir1, const char *dir2, const char *name, struct dirent *de) 345{
|
| 346 damage++; 347 change++;
|
263 if (de->d_type == DT_DIR) { 264 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 265 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 266 DoDir(dir1,dir2,p); 267 printf("CTMDR %s%s\n",name,de->d_name); 268 s_del_dirs++; 269 } else if (de->d_type == DT_REG) { 270 char *buf1 = alloca(strlen(dir1) + strlen(name) + 271 strlen(de->d_name) + 3); 272 char *m1, md5_1[33]; 273 strcpy(buf1,dir1); 274 strcat(buf1,"/"); strcat(buf1,name); 275 strcat(buf1,"/"); strcat(buf1,de->d_name); 276 m1 = MD5File(buf1, md5_1); 277 printf("CTMFR %s%s %s\n",name,de->d_name,m1); 278 s_del_files++; 279 s_del_bytes += StatFile(buf1)->st_size; 280 } 281} 282 283void 284GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u_long *ignored, u_long *bogus, u_long *wrong) 285{ 286 char buf[BUFSIZ]; 287 288 for (;;) { 289 for (;;) { 290 (*i)++; 291 if (*i >= *n) 292 return; 293 *buf = 0; 294 if (*dir != '/') 295 strcat(buf,"/"); 296 strcat(buf,dir); 297 if (buf[strlen(buf)-1] != '/') 298 strcat(buf,"/"); 299 strcat(buf,name); 300 if (buf[strlen(buf)-1] != '/') 301 strcat(buf,"/");
| 348 if (de->d_type == DT_DIR) { 349 char *p = alloca(strlen(name)+strlen(de->d_name)+2); 350 strcpy(p,name); strcat(p,de->d_name); strcat(p, "/"); 351 DoDir(dir1,dir2,p); 352 printf("CTMDR %s%s\n",name,de->d_name); 353 s_del_dirs++; 354 } else if (de->d_type == DT_REG) { 355 char *buf1 = alloca(strlen(dir1) + strlen(name) + 356 strlen(de->d_name) + 3); 357 char *m1, md5_1[33]; 358 strcpy(buf1,dir1); 359 strcat(buf1,"/"); strcat(buf1,name); 360 strcat(buf1,"/"); strcat(buf1,de->d_name); 361 m1 = MD5File(buf1, md5_1); 362 printf("CTMFR %s%s %s\n",name,de->d_name,m1); 363 s_del_files++; 364 s_del_bytes += StatFile(buf1)->st_size; 365 } 366} 367 368void 369GetNext(int *i, int *n, struct dirent **nl, const char *dir, const char *name, u_long *ignored, u_long *bogus, u_long *wrong) 370{ 371 char buf[BUFSIZ]; 372 373 for (;;) { 374 for (;;) { 375 (*i)++; 376 if (*i >= *n) 377 return; 378 *buf = 0; 379 if (*dir != '/') 380 strcat(buf,"/"); 381 strcat(buf,dir); 382 if (buf[strlen(buf)-1] != '/') 383 strcat(buf,"/"); 384 strcat(buf,name); 385 if (buf[strlen(buf)-1] != '/') 386 strcat(buf,"/");
|
302 fprintf(stderr,">%d<%s>\n",strlen(nl[*i]->d_name),nl[*i]->d_name); 303 fflush(stderr);
| |
304 strcat(buf,nl[*i]->d_name);
| 387 strcat(buf,nl[*i]->d_name);
|
305 if (flag_ignore && !regexec(®_ignore,buf,0,0,0))
| 388 if (flag_ignore && 389 !regexec(®_ignore,buf,0,0,0)) {
|
306 (*ignored)++;
| 390 (*ignored)++;
|
307 else if (flag_bogus && !regexec(®_bogus,buf,0,0,0))
| 391 if (verbose > 2) { 392 fprintf(stderr,"Ignore %s\n",buf); 393 } 394 } else if (flag_bogus && 395 !regexec(®_bogus,buf,0,0,0)) {
|
308 (*bogus)++;
| 396 (*bogus)++;
|
309 else
| 397 if (verbose > 0) { 398 fprintf(stderr,"Bogus %s\n",buf); 399 } 400 } else {
|
310 break;
| 401 break;
|
| 402 }
|
311 free(nl[*i]); nl[*i] = 0; 312 } 313 /* If the filesystem didn't tell us, find type */ 314 if (nl[*i]->d_type == DT_UNKNOWN) 315 nl[*i]->d_type = IFTODT(StatFile(buf)->st_mode); 316 if (nl[*i]->d_type == DT_REG || nl[*i]->d_type == DT_DIR) 317 break; 318 (*wrong)++;
| 403 free(nl[*i]); nl[*i] = 0; 404 } 405 /* If the filesystem didn't tell us, find type */ 406 if (nl[*i]->d_type == DT_UNKNOWN) 407 nl[*i]->d_type = IFTODT(StatFile(buf)->st_mode); 408 if (nl[*i]->d_type == DT_REG || nl[*i]->d_type == DT_DIR) 409 break; 410 (*wrong)++;
|
| 411 if (verbose > 0) 412 fprintf(stderr,"Wrong %s\n",buf);
|
319 free(nl[*i]); nl[*i] = 0; 320 } 321} 322 323void 324DoDir(const char *dir1, const char *dir2, const char *name) 325{ 326 int i1,i2,n1,n2,i; 327 struct dirent **nl1,**nl2; 328 char *buf1 = alloca(strlen(dir1) + strlen(name) + 4); 329 char *buf2 = alloca(strlen(dir2) + strlen(name) + 4); 330 331 strcpy(buf1,dir1); strcat(buf1,"/"); strcat(buf1,name); 332 strcpy(buf2,dir2); strcat(buf2,"/"); strcat(buf2,name); 333 n1 = scandir(buf1, &nl1, dirselect, alphasort); 334 n2 = scandir(buf2, &nl2, dirselect, alphasort); 335 i1 = i2 = -1; 336 GetNext(&i1, &n1, nl1, dir1, name, &s1_ignored, &s1_bogus, &s1_wrong); 337 GetNext(&i2, &n2, nl2, dir2, name, &s2_ignored, &s2_bogus, &s2_wrong); 338 for (;i1 < n1 || i2 < n2;) { 339
| 413 free(nl[*i]); nl[*i] = 0; 414 } 415} 416 417void 418DoDir(const char *dir1, const char *dir2, const char *name) 419{ 420 int i1,i2,n1,n2,i; 421 struct dirent **nl1,**nl2; 422 char *buf1 = alloca(strlen(dir1) + strlen(name) + 4); 423 char *buf2 = alloca(strlen(dir2) + strlen(name) + 4); 424 425 strcpy(buf1,dir1); strcat(buf1,"/"); strcat(buf1,name); 426 strcpy(buf2,dir2); strcat(buf2,"/"); strcat(buf2,name); 427 n1 = scandir(buf1, &nl1, dirselect, alphasort); 428 n2 = scandir(buf2, &nl2, dirselect, alphasort); 429 i1 = i2 = -1; 430 GetNext(&i1, &n1, nl1, dir1, name, &s1_ignored, &s1_bogus, &s1_wrong); 431 GetNext(&i2, &n2, nl2, dir2, name, &s2_ignored, &s2_bogus, &s2_wrong); 432 for (;i1 < n1 || i2 < n2;) { 433
|
| 434 if (damage_limit && damage > damage_limit) 435 break; 436
|
340 /* Get next item from list 1 */ 341 if (i1 < n1 && !nl1[i1]) 342 GetNext(&i1, &n1, nl1, dir1, name, 343 &s1_ignored, &s1_bogus, &s1_wrong); 344 345 /* Get next item from list 2 */ 346 if (i2 < n2 && !nl2[i2]) 347 GetNext(&i2, &n2, nl2, dir2, name, 348 &s2_ignored, &s2_bogus, &s2_wrong); 349 350 if (i1 >= n1 && i2 >= n2) { 351 /* Done */ 352 break; 353 } else if (i1 >= n1 && i2 < n2) { 354 /* end of list 1, add anything left on list 2 */ 355 Add(dir1,dir2,name,nl2[i2]); 356 free(nl2[i2]); nl2[i2] = 0; 357 } else if (i1 < n1 && i2 >= n2) { 358 /* end of list 2, delete anything left on list 1 */ 359 Del(dir1,dir2,name,nl1[i1]); 360 free(nl1[i1]); nl1[i1] = 0; 361 } else if (!(i = strcmp(nl1[i1]->d_name, nl2[i2]->d_name))) { 362 /* Identical names */ 363 if (nl1[i1]->d_type == nl2[i2]->d_type) { 364 /* same type */ 365 Equ(dir1,dir2,name,nl1[i1]); 366 } else { 367 /* different types */ 368 Del(dir1,dir2,name,nl1[i1]); 369 Add(dir1,dir2,name,nl2[i2]); 370 } 371 free(nl1[i1]); nl1[i1] = 0; 372 free(nl2[i2]); nl2[i2] = 0; 373 } else if (i < 0) { 374 /* Something extra in list 1, delete it */ 375 Del(dir1,dir2,name,nl1[i1]); 376 free(nl1[i1]); nl1[i1] = 0; 377 } else { 378 /* Something extra in list 2, add it */ 379 Add(dir1,dir2,name,nl2[i2]); 380 free(nl2[i2]); nl2[i2] = 0; 381 } 382 } 383 if (n1 >= 0) 384 free(nl1); 385 if (n2 >= 0) 386 free(nl2); 387} 388 389int 390main(int argc, char **argv) 391{ 392 int i; 393 extern char *optarg; 394 extern int optind; 395
| 437 /* Get next item from list 1 */ 438 if (i1 < n1 && !nl1[i1]) 439 GetNext(&i1, &n1, nl1, dir1, name, 440 &s1_ignored, &s1_bogus, &s1_wrong); 441 442 /* Get next item from list 2 */ 443 if (i2 < n2 && !nl2[i2]) 444 GetNext(&i2, &n2, nl2, dir2, name, 445 &s2_ignored, &s2_bogus, &s2_wrong); 446 447 if (i1 >= n1 && i2 >= n2) { 448 /* Done */ 449 break; 450 } else if (i1 >= n1 && i2 < n2) { 451 /* end of list 1, add anything left on list 2 */ 452 Add(dir1,dir2,name,nl2[i2]); 453 free(nl2[i2]); nl2[i2] = 0; 454 } else if (i1 < n1 && i2 >= n2) { 455 /* end of list 2, delete anything left on list 1 */ 456 Del(dir1,dir2,name,nl1[i1]); 457 free(nl1[i1]); nl1[i1] = 0; 458 } else if (!(i = strcmp(nl1[i1]->d_name, nl2[i2]->d_name))) { 459 /* Identical names */ 460 if (nl1[i1]->d_type == nl2[i2]->d_type) { 461 /* same type */ 462 Equ(dir1,dir2,name,nl1[i1]); 463 } else { 464 /* different types */ 465 Del(dir1,dir2,name,nl1[i1]); 466 Add(dir1,dir2,name,nl2[i2]); 467 } 468 free(nl1[i1]); nl1[i1] = 0; 469 free(nl2[i2]); nl2[i2] = 0; 470 } else if (i < 0) { 471 /* Something extra in list 1, delete it */ 472 Del(dir1,dir2,name,nl1[i1]); 473 free(nl1[i1]); nl1[i1] = 0; 474 } else { 475 /* Something extra in list 2, add it */ 476 Add(dir1,dir2,name,nl2[i2]); 477 free(nl2[i2]); nl2[i2] = 0; 478 } 479 } 480 if (n1 >= 0) 481 free(nl1); 482 if (n2 >= 0) 483 free(nl2); 484} 485 486int 487main(int argc, char **argv) 488{ 489 int i; 490 extern char *optarg; 491 extern int optind; 492
|
| 493 setbuf(stderr, NULL); 494
|
396 if (regcomp(®_bogus,DEFAULT_BOGUS, REG_EXTENDED | REG_NEWLINE)) 397 /* XXX use regerror to explain it */ 398 err(1,"Default regular expression argument to -B is botched"); 399 flag_bogus = 1; 400 401 if (regcomp(®_ignore,DEFAULT_IGNORE, REG_EXTENDED | REG_NEWLINE)) 402 /* XXX use regerror to explain it */ 403 err(1,"Default regular expression argument to -I is botched"); 404 flag_ignore = 1; 405
| 495 if (regcomp(®_bogus,DEFAULT_BOGUS, REG_EXTENDED | REG_NEWLINE)) 496 /* XXX use regerror to explain it */ 497 err(1,"Default regular expression argument to -B is botched"); 498 flag_bogus = 1; 499 500 if (regcomp(®_ignore,DEFAULT_IGNORE, REG_EXTENDED | REG_NEWLINE)) 501 /* XXX use regerror to explain it */ 502 err(1,"Default regular expression argument to -I is botched"); 503 flag_ignore = 1; 504
|
406 while ((i = getopt(argc,argv,"I:B:")) != EOF)
| 505 while ((i = getopt(argc,argv,"D:I:B:qv")) != EOF)
|
407 switch (i) {
| 506 switch (i) {
|
| 507 case 'D': 508 damage_limit = strtol(optarg,0,0); 509 if (damage_limit < 0) 510 err(1,"Damage limit must be positive"); 511 break;
|
408 case 'I': 409 if (flag_ignore) 410 regfree(®_ignore); 411 flag_ignore = 0; 412 if (!*optarg) 413 break; 414 if (regcomp(®_ignore,optarg, 415 REG_EXTENDED | REG_NEWLINE)) 416 /* XXX use regerror to explain it */ 417 err(1,"Regular expression argument to -I is botched"); 418 flag_ignore = 1; 419 break; 420 case 'B': 421 if (flag_bogus) 422 regfree(®_bogus); 423 flag_bogus = 0; 424 if (!*optarg) 425 break; 426 if (regcomp(®_bogus,optarg, 427 REG_EXTENDED | REG_NEWLINE)) 428 /* XXX use regerror to explain it */ 429 err(1,"Regular expression argument to -B is botched"); 430 flag_bogus = 1; 431 break;
| 512 case 'I': 513 if (flag_ignore) 514 regfree(®_ignore); 515 flag_ignore = 0; 516 if (!*optarg) 517 break; 518 if (regcomp(®_ignore,optarg, 519 REG_EXTENDED | REG_NEWLINE)) 520 /* XXX use regerror to explain it */ 521 err(1,"Regular expression argument to -I is botched"); 522 flag_ignore = 1; 523 break; 524 case 'B': 525 if (flag_bogus) 526 regfree(®_bogus); 527 flag_bogus = 0; 528 if (!*optarg) 529 break; 530 if (regcomp(®_bogus,optarg, 531 REG_EXTENDED | REG_NEWLINE)) 532 /* XXX use regerror to explain it */ 533 err(1,"Regular expression argument to -B is botched"); 534 flag_bogus = 1; 535 break;
|
| 536 case 'q': 537 verbose--; 538 break; 539 case 'v': 540 verbose++; 541 break;
|
432 case '?': 433 default:
| 542 case '?': 543 default:
|
434 fprintf(stderr,"Usage:\n\t%s: %s\n", argv[0], 435"[-I ignore_re] [-B bogus_re]");
| 544 Usage();
|
436 return (1); 437 } 438 argc -= optind; 439 argv += optind; 440 441 setbuf(stdout,0); 442
| 545 return (1); 546 } 547 argc -= optind; 548 argv += optind; 549 550 setbuf(stdout,0); 551
|
| 552 if (argc != 6) { 553 Usage(); 554 return (1); 555 } 556
|
443 signal(SIGINFO,stat_info);
| 557 signal(SIGINFO,stat_info);
|
444 printf("CTM_BEGIN 2.0 tst 0 950326022230Z .\n"); 445 DoDir(argv[0],argv[1],""); 446 printf("CTM_END "); 447 print_stat(stderr,"");
| 558 559 printf("CTM_BEGIN 2.0 %s %s %s %s\n", 560 argv[0], argv[1], argv[2], argv[3]); 561 DoDir(argv[4],argv[5],""); 562 if (damage_limit && damage > damage_limit) { 563 print_stat(stderr,""); 564 err(1,"Damage would exceede %d files", damage_limit); 565 } else if (!change) { 566 err(1,"No changes"); 567 } else { 568 printf("CTM_END "); 569 print_stat(stderr,""); 570 }
|
448 exit(0); 449}
| 571 exit(0); 572}
|