$OpenBSD: patch-ctm_ctm_ctm_pass2_c,v 1.2 2007/10/31 23:14:46 ajacoutot Exp $
--- ctm/ctm/ctm_pass2.c.orig	Wed Oct 31 23:06:34 2007
+++ ctm/ctm/ctm_pass2.c	Wed Oct 31 23:06:34 2007
@@ -27,7 +27,10 @@ Pass2(FILE *fd)
     struct CTM_Syntax *sp;
     struct stat st;
     int ret = 0;
+    int match = 0;
     char md5_1[33];
+    struct CTM_Filter *filter;
+    FILE *ed = NULL;
 
     if(Verbose>3)
 	printf("Pass2 -- Checking if CTM-patch will apply\n");
@@ -49,6 +52,12 @@ Pass2(FILE *fd)
 	Delete(md5);
 	cnt = -1;
 
+	/* if a filter list was specified, check file name against
+	   the filters specified 
+	   if no filter was given operate on all files. */
+	match = (FilterList ? 
+		    !(FilterList->Action) : CTM_FILTER_ENABLE);
+
 	GETFIELD(p,' ');
 
 	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
@@ -70,6 +79,22 @@ Pass2(FILE *fd)
 	    switch (j & CTM_F_MASK) {
 		case CTM_F_Name:
 		    GETNAMECOPY(name,sep,j,0);
+		    /* If `keep' was specified, we won't remove any files,
+		       so don't check if the file exists */
+		    if (KeepIt &&
+			(!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) {
+			match = CTM_FILTER_DISABLE;
+			break;
+		    }
+
+		    for (filter = FilterList; filter; filter = filter->Next)				if (0 == regexec(&filter->CompiledRegex, name,
+				    0, 0, 0)) {
+				    match = filter->Action;
+			    }
+
+		    if (CTM_FILTER_DISABLE == match)
+			    break;	/* should ignore this file */
+
 		    /* XXX Check DR DM rec's for parent-dir */
 		    if(j & CTM_Q_Name_New) {
 			/* XXX Check DR FR rec's for item */
@@ -89,6 +114,11 @@ Pass2(FILE *fd)
 			    ret |= Exit_NotOK;
 			break;
 		    }
+		    if (-1 == access(name, W_OK)) {
+			fprintf(stderr, "  %s: %s not writable.\n",
+				sp->Key, name);
+			ret |= Exit_Forcible;
+		    }
 		    if (SetTime && getuid() && (getuid() != st.st_uid)) {
 			    fprintf(stderr,
 				"  %s: %s not mine, cannot set time.\n",
@@ -124,7 +154,7 @@ Pass2(FILE *fd)
 		    if(j & CTM_Q_MD5_Before) {
 		        char *tmp;
 			GETFIELD(p,sep);
-			if((st.st_mode & S_IFMT) == S_IFREG &&
+			if(match && (st.st_mode & S_IFMT) == S_IFREG &&
 			  (tmp = MD5File(name,md5_1)) != NULL &&
 			  strcmp(tmp,p)) {
 			    fprintf(stderr,"  %s: %s md5 mismatch.\n",
@@ -154,6 +184,8 @@ Pass2(FILE *fd)
 		case CTM_F_Bytes:
 		    if(cnt < 0) WRONG
 		    GETDATA(trash,cnt);
+		    if (!match)
+			break;
 		    if(!strcmp(sp->Key,"FN")) {
 			p = tempnam(TmpDir,"CTMclient");
 			j = ctm_edit(trash,cnt,name,p);
@@ -171,6 +203,30 @@ Pass2(FILE *fd)
 			    unlink(p);
 			    Free(p);
 			    return ret;
+			}
+		        unlink(p);
+			Free(p);
+		    } else if (!strcmp(sp->Key,"FE")) {
+			p = tempnam(TmpDir,"CTMclient");
+			ed = popen("ed","w");
+			if (!ed) {
+			    WRONG
+			}
+			fprintf(ed,"e %s\n", name);
+			if (cnt != fwrite(trash,1,cnt,ed)) {
+			    warn("%s", name);
+			    pclose(ed);
+			    WRONG
+			}
+			fprintf(ed,"w %s\n",p);
+			if (pclose(ed)) {
+			    warn("%s", p);
+			    WRONG
+			}
+			if(strcmp(md5,MD5File(p,md5_1))) {
+			    fprintf(stderr,"%s %s MD5 didn't come out right\n",
+				sp->Key, name);
+			    WRONG
 			}
 		        unlink(p);
 			Free(p);
