ctm_pass3.c revision 2926
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$
10 *
11 */
12
13#include "ctm.h"
14#define BADREAD 32
15
16/*---------------------------------------------------------------------------*/
17/* Pass3 -- Validate the incomming CTM-file.
18 */
19
20int
21Pass3(FILE *fd)
22{
23    u_char *p,*q,buf[BUFSIZ];
24    MD5_CTX ctx;
25    int i,j,sep,cnt;
26    u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
27    struct CTM_Syntax *sp;
28    FILE *ed=0;
29    struct stat st;
30
31    if(Verbose>3)
32	printf("Pass3 -- Applying the CTM-patch\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    GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
39    GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
40    GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
41
42    for(;;) {
43	if(md5)		{Free(md5), md5 = 0;}
44	if(uid)		{Free(uid), uid = 0;}
45	if(gid)		{Free(gid), gid = 0;}
46	if(mode)	{Free(mode), mode = 0;}
47	if(md5before)	{Free(md5before), md5before = 0;}
48	if(trash)	{Free(trash), trash = 0;}
49	if(name)	{Free(name), name = 0;}
50	cnt = -1;
51
52	GETFIELD(p,' ');
53
54	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
55
56	if(!strcmp(p+3,"_END"))
57	    break;
58
59	for(sp=Syntax;sp->Key;sp++)
60	    if(!strcmp(p+3,sp->Key))
61		goto found;
62	WRONG
63    found:
64	for(i=0;(j = sp->List[i]);i++) {
65	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
66		sep = ' ';
67	    else
68		sep = '\n';
69
70	    switch (j & CTM_F_MASK) {
71		case CTM_F_Name: GETFIELDCOPY(name,sep); break;
72		case CTM_F_Uid:  GETFIELDCOPY(uid,sep); break;
73		case CTM_F_Gid:  GETFIELDCOPY(gid,sep); break;
74		case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
75		case CTM_F_MD5:
76		    if(j & CTM_Q_MD5_Before)
77			GETFIELDCOPY(md5before,sep);
78		    else
79			GETFIELDCOPY(md5,sep);
80		    break;
81		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
82		case CTM_F_Bytes: GETDATA(trash,cnt); break;
83		default: WRONG
84		}
85	    }
86	j = strlen(name)-1;
87	if(name[j] == '/') name[j] = '\0';
88	fprintf(stderr,"> %s %s\n",sp->Key,name);
89	if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
90	    i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0644);
91	    if(i < 0) {
92		perror(name);
93		continue;
94	    }
95	    if(cnt != write(i,trash,cnt)) {
96		perror(name);
97		continue;
98	    }
99	    close(i);
100	    if(strcmp(md5,MD5File(name))) {
101		fprintf(stderr,"  %s %s MD5 didn't come out right\n",
102		   sp->Key,name);
103		continue;
104	    }
105	    continue;
106	}
107	if(!strcmp(sp->Key,"FE")) {
108	    ed = popen("ed","w");
109	    if(!ed) {
110		WRONG
111	    }
112	    fprintf(ed,"e %s\n",name);
113	    if(cnt != fwrite(trash,1,cnt,ed)) {
114		perror(name);
115		pclose(ed);
116		continue;
117	    }
118	    fprintf(ed,"w %s\n",name);
119	    if(pclose(ed)) {
120		perror("ed");
121		continue;
122	    }
123	    if(strcmp(md5,MD5File(name))) {
124		fprintf(stderr,"  %s %s MD5 didn't come out right\n",
125		   sp->Key,name);
126		continue;
127	    }
128	    continue;
129	}
130	if(!strcmp(sp->Key,"FN")) {
131	    strcpy(buf,name);
132	    strcat(buf,".ctm");
133	    i = ctm_edit(trash,cnt,name,buf);
134	    if(i) {
135	    }
136	    rename(buf,name);
137	}
138	if(!strcmp(sp->Key,"DM")) {
139	    if(0 > mkdir(name,0755)) {
140		sprintf(buf,"mkdir -p %s",name);
141		system(buf);
142	    }
143	    if(0 > stat(name,&st) || ((st.st_mode & S_IFMT) != S_IFDIR)) {
144		fprintf(stderr,"<%s> mkdir failed\n",name);
145		exit(1);
146	    }
147	    continue;
148	}
149	if(!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")) {
150	    if(0 > unlink(name)) {
151		sprintf(buf,"rm -rf %s",name);
152		system(buf);
153	    }
154	    continue;
155	}
156	WRONG
157    }
158    q = MD5End (&ctx);
159    GETFIELD(p,'\n');
160    if(strcmp(q,p)) WRONG
161    if (-1 != getc(fd)) WRONG
162    return 0;
163}
164