$OpenBSD: patch-ctm_ctm_ctm_pass3_c,v 1.2 2007/10/31 23:14:46 ajacoutot Exp $
--- ctm/ctm/ctm_pass3.c.orig	Wed Oct 31 23:06:34 2007
+++ ctm/ctm/ctm_pass3.c	Wed Oct 31 23:06:34 2007
@@ -22,7 +22,7 @@ settime(const char *name, const struct timeval *times)
 {
 	if (SetTime)
 	    if (utimes(name,times)) {
-		fprintf(stderr, "  utimes(): %s: %s\n", name, strerror(errno));
+		warn("utimes(): %s", name);
 		return -1;
 	    }
 	return 0;
@@ -39,8 +39,9 @@ Pass3(FILE *fd)
     FILE *ed=0;
     struct stat st;
     char md5_1[33];
+    int match=0;
     struct timeval times[2];
-
+    struct CTM_Filter *filter = NULL;
     if(Verbose>3)
 	printf("Pass3 -- Applying the CTM-patch\n");
     MD5Init (&ctx);
@@ -139,10 +140,11 @@ Pass3(FILE *fd)
 		case CTM_F_Gid:  GETFIELDCOPY(gid,sep); break;
 		case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
 		case CTM_F_MD5:
-		    if(j & CTM_Q_MD5_Before)
+		    if(j & CTM_Q_MD5_Before) {
 			GETFIELDCOPY(md5before,sep);
-		    else
+		    } else {
 			GETFIELDCOPY(md5,sep);
+		    }
 		    break;
 		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
 		case CTM_F_Bytes: GETDATA(trash,cnt); break;
@@ -153,15 +155,55 @@ Pass3(FILE *fd)
 	j = strlen(name)-1;
 	if(name[j] == '/') name[j] = '\0';
 
-	fprintf(stderr,"> %s %s\n",sp->Key,name);
+	/*
+	 * If a filter list is specified, run thru the filter list and
+	 * match `name' against filters.  If the name matches, set the
+	 * required action to that specified in the filter.
+	 * The default action if no filterlist is given is to match
+	 * everything.  
+	 */
+
+	match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
+	for (filter = FilterList; filter; filter = filter->Next) {
+	    if (0 == regexec(&filter->CompiledRegex, name,
+		0, 0, 0)) {
+		match = filter->Action;
+	    }
+	}
+
+	if (CTM_FILTER_DISABLE == match) /* skip file if disabled */
+		continue;
+
+	if (Verbose > 0)
+		fprintf(stderr,"> %s %s\n",sp->Key,name);
+	if ((strcmp(sp->Key, "FS") == 0 ||
+	     strcmp(sp->Key, "FN") == 0 ||
+	     strcmp(sp->Key, "FE") == 0) && -1 == access(name, W_OK)) {
+		if (Verbose > 1)
+			fprintf(stderr, "  %s: chmod u+w %s\n", 
+			    sp->Key, name);
+		if (!Force) {
+			warn("%s", name);
+			WRONG
+		}
+		if (-1 == stat(name, &st)) {
+			warn("stat: %s", name);
+			WRONG
+		}
+		if (-1 == chmod(name, st.st_mode | S_IWUSR)) {
+			warn("chmod: %s", name);
+			WRONG
+		}
+	}
+
 	if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
 	    i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
 	    if(i < 0) {
-		perror(name);
+		warn("%s", name);
 		WRONG
 	    }
 	    if(cnt != write(i,trash,cnt)) {
-		perror(name);
+		warn("%s", name);
 		WRONG
 	    }
 	    close(i);
@@ -180,13 +222,13 @@ Pass3(FILE *fd)
 	    }
 	    fprintf(ed,"e %s\n",name);
 	    if(cnt != fwrite(trash,1,cnt,ed)) {
-		perror(name);
+		warn("%s", name);
 		pclose(ed);
 		WRONG
 	    }
 	    fprintf(ed,"w %s\n",name);
 	    if(pclose(ed)) {
-		perror("ed");
+		warn("ed");
 		WRONG
 	    }
 	    if(strcmp(md5,MD5File(name,md5_1))) {
@@ -206,12 +248,13 @@ Pass3(FILE *fd)
 		    sp->Key,name,i);
 	        WRONG
 	    }
-	    rename(buf,name);
-	    if(strcmp(md5,MD5File(name,md5_1))) {
+	    if(strcmp(md5,MD5File(buf,md5_1))) {
 		fprintf(stderr," %s %s Edit failed MD5 check.\n",
 		    sp->Key,name);
 	        WRONG
 	    }
+	    if (rename(buf,name) == -1)
+		WRONG
 	    if (settime(name,times)) WRONG
 	    continue;
 	}
@@ -228,7 +271,11 @@ Pass3(FILE *fd)
 	    continue;
 	}
 	if(!strcmp(sp->Key,"FR")) {
-	    if (0 != unlink(name)) {
+	    if (KeepIt) { 
+		if (Verbose > 1) 
+			printf("<%s> not removed\n", name);
+	    }
+	    else if (0 != unlink(name)) {
 		fprintf(stderr,"<%s> unlink failed\n",name);
 		if (!Force)
 		    WRONG
@@ -240,8 +287,14 @@ Pass3(FILE *fd)
 	     * We cannot use rmdir() because we do not get the directories
 	     * in '-depth' order (cvs-cur.0018.gz for examples)
 	     */
-	    sprintf(buf,"rm -rf %s",name);
-	    system(buf);
+	    if (KeepIt) {
+		if (Verbose > 1) {
+			printf("<%s> not removed\n", name);
+		}
+	    } else {
+		    sprintf(buf,"rm -rf %s",name);
+		    system(buf);
+	    }
 	    continue;
 	}
 	WRONG
