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