ctm_pass2.c revision 8857
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $Id: ctm_pass2.c,v 1.7 1995/03/19 12:01:23 roberto Exp $
10 *
11 */
12
13#include "ctm.h"
14#define BADREAD 32
15
16/*---------------------------------------------------------------------------*/
17/* Pass2 -- Validate the incoming CTM-file.
18 */
19
20int
21Pass2(FILE *fd)
22{
23    u_char *p,*q,*md5=0;
24    MD5_CTX ctx;
25    int i,j,sep,cnt;
26    u_char *trash=0,*name=0;
27    struct CTM_Syntax *sp;
28    struct stat st;
29    int ret = 0;
30
31    if(Verbose>3)
32	printf("Pass2 -- Checking if CTM-patch will apply\n");
33    MD5Init (&ctx);
34
35    GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
36    GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
37    GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
38    /* XXX Lookup name in /etc/ctm,conf, read stuff */
39    GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
40    /* XXX Verify that this is the next patch to apply */
41    GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
42    GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
43    /* XXX drop or use ? */
44
45    for(;;) {
46	if(trash)	{Free(trash), trash = 0;}
47	if(name)	{Free(name), name = 0;}
48	if(md5)		{Free(md5), md5 = 0;}
49	cnt = -1;
50
51	GETFIELD(p,' ');
52
53	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
54
55	if(!strcmp(p+3,"_END"))
56	    break;
57
58	for(sp=Syntax;sp->Key;sp++)
59	    if(!strcmp(p+3,sp->Key))
60		goto found;
61	WRONG
62    found:
63	for(i=0;(j = sp->List[i]);i++) {
64	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
65		sep = ' ';
66	    else
67		sep = '\n';
68
69	    switch (j & CTM_F_MASK) {
70		case CTM_F_Name:
71		    GETFIELDCOPY(name,sep);
72		    /* XXX Check DR DM rec's for parent-dir */
73		    if(j & CTM_Q_Name_New) {
74			/* XXX Check DR FR rec's for item */
75			if(-1 != stat(name,&st)) {
76			    fprintf(stderr,"  %s: %s exists.\n",
77				sp->Key,name);
78			    ret |= Exit_Forcible;
79			}
80			break;
81		    }
82		    if(-1 == stat(name,&st)) {
83			fprintf(stderr,"  %s: %s doesn't exist.\n",
84			    sp->Key,name);
85		        if (sp->Key[1] == 'R')
86			    ret |= Exit_Forcible;
87			else
88			    ret |= Exit_NotOK;
89			break;
90		    }
91		    if (j & CTM_Q_Name_Dir) {
92			if((st.st_mode & S_IFMT) != S_IFDIR) {
93			    fprintf(stderr,
94				"  %s: %s exist, but isn't dir.\n",
95				sp->Key,name);
96			    ret |= Exit_NotOK;
97			}
98			break;
99		    }
100		    if (j & CTM_Q_Name_File) {
101			if((st.st_mode & S_IFMT) != S_IFREG) {
102			    fprintf(stderr,
103				"  %s: %s exist, but isn't file.\n",
104				sp->Key,name);
105			    ret |= Exit_NotOK;
106			}
107			break;
108		    }
109		    break;
110		case CTM_F_Uid:
111		case CTM_F_Gid:
112		case CTM_F_Mode:
113		    GETFIELD(p,sep);
114		    break;
115		case CTM_F_MD5:
116		    if(!name) WRONG
117		    if(j & CTM_Q_MD5_Before) {
118			GETFIELD(p,sep);
119			if((st.st_mode & S_IFMT) == S_IFREG &&
120			  strcmp(MD5File(name),p)) {
121			    fprintf(stderr,"  %s: %s md5 mismatch.\n",
122				sp->Key,name);
123			    if(j & CTM_Q_MD5_Force) {
124				if(Force)
125				    fprintf(stderr,"  Can and will force.\n");
126				else
127				    fprintf(stderr,"  Could have forced.\n");
128				ret |= Exit_Forcible;
129			    } else {
130				ret |= Exit_NotOK;
131			    }
132			}
133			break;
134		    }
135		    if(j & CTM_Q_MD5_After) {
136			GETFIELDCOPY(md5,sep);
137			break;
138		    }
139		    /* Unqualified MD5 */
140		    WRONG
141		    break;
142		case CTM_F_Count:
143		    GETBYTECNT(cnt,sep);
144		    break;
145		case CTM_F_Bytes:
146		    if(cnt < 0) WRONG
147		    GETDATA(trash,cnt);
148		    if(!strcmp(sp->Key,"FN")) {
149			p = tempnam(TmpDir,"CTMclient");
150			j = ctm_edit(trash,cnt,name,p);
151			if(j) {
152			    fprintf(stderr,"  %s: %s edit returned %d.\n",
153				sp->Key,name,j);
154			    ret |= j;
155			    return ret;
156			} else if(strcmp(md5,MD5File(p))) {
157			    fprintf(stderr,"  %s: %s edit fails.\n",
158				sp->Key,name);
159			    ret |= Exit_Mess;
160			    return ret;
161			}
162			unlink(p);
163			free(p);
164		    }
165
166		    break;
167		default: WRONG
168	    }
169        }
170    }
171    q = MD5End (&ctx);
172    GETFIELD(p,'\n');			/* <MD5> */
173    if(strcmp(q,p)) WRONG
174    if (-1 != getc(fd)) WRONG
175    return ret;
176}
177