ctm_pass3.c revision 13917
12926Sphk/*
22926Sphk * ----------------------------------------------------------------------------
32926Sphk * "THE BEER-WARE LICENSE" (Revision 42):
42926Sphk * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
52926Sphk * can do whatever you want with this stuff. If we meet some day, and you think
62926Sphk * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
72926Sphk * ----------------------------------------------------------------------------
82926Sphk *
913917Sphk * $Id: ctm_pass3.c,v 1.11 1995/07/12 09:16:13 phk Exp $
102926Sphk *
112926Sphk */
122926Sphk
132886Sphk#include "ctm.h"
142926Sphk#define BADREAD 32
152886Sphk
162886Sphk/*---------------------------------------------------------------------------*/
174816Sphk/* Pass3 -- Validate the incoming CTM-file.
182886Sphk */
192886Sphk
202886Sphkint
212886SphkPass3(FILE *fd)
222886Sphk{
232886Sphk    u_char *p,*q,buf[BUFSIZ];
242886Sphk    MD5_CTX ctx;
252886Sphk    int i,j,sep,cnt;
262886Sphk    u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
272886Sphk    struct CTM_Syntax *sp;
282886Sphk    FILE *ed=0;
292886Sphk    struct stat st;
309491Sphk    char md5_1[33];
312886Sphk
328857Srgrimes    if(Verbose>3)
332886Sphk	printf("Pass3 -- Applying the CTM-patch\n");
342886Sphk    MD5Init (&ctx);
352886Sphk
362886Sphk    GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
372886Sphk    GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
382886Sphk    GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
392886Sphk    GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
402886Sphk    GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
412886Sphk    GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
422886Sphk
432886Sphk    for(;;) {
4413917Sphk	Delete(md5);
4513917Sphk	Delete(uid);
4613917Sphk	Delete(gid);
4713917Sphk	Delete(mode);
4813917Sphk	Delete(md5before);
4913917Sphk	Delete(trash);
5013917Sphk	Delete(name);
512886Sphk	cnt = -1;
522886Sphk
532886Sphk	GETFIELD(p,' ');
542886Sphk
552886Sphk	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
562886Sphk
572886Sphk	if(!strcmp(p+3,"_END"))
582886Sphk	    break;
592886Sphk
602886Sphk	for(sp=Syntax;sp->Key;sp++)
612886Sphk	    if(!strcmp(p+3,sp->Key))
622886Sphk		goto found;
632886Sphk	WRONG
642886Sphk    found:
652886Sphk	for(i=0;(j = sp->List[i]);i++) {
662886Sphk	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
672886Sphk		sep = ' ';
682886Sphk	    else
692886Sphk		sep = '\n';
702886Sphk
712886Sphk	    switch (j & CTM_F_MASK) {
7213917Sphk		case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break;
732886Sphk		case CTM_F_Uid:  GETFIELDCOPY(uid,sep); break;
742886Sphk		case CTM_F_Gid:  GETFIELDCOPY(gid,sep); break;
752886Sphk		case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
762886Sphk		case CTM_F_MD5:
772886Sphk		    if(j & CTM_Q_MD5_Before)
788857Srgrimes			GETFIELDCOPY(md5before,sep);
792886Sphk		    else
808857Srgrimes			GETFIELDCOPY(md5,sep);
812886Sphk		    break;
822886Sphk		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
832886Sphk		case CTM_F_Bytes: GETDATA(trash,cnt); break;
842886Sphk		default: WRONG
852886Sphk		}
862886Sphk	    }
872948Sphk	/* XXX This should go away.  Disallow trailing '/' */
882886Sphk	j = strlen(name)-1;
892886Sphk	if(name[j] == '/') name[j] = '\0';
902948Sphk
912886Sphk	fprintf(stderr,"> %s %s\n",sp->Key,name);
922886Sphk	if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) {
937372Sjoerg	    i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0666);
942886Sphk	    if(i < 0) {
952886Sphk		perror(name);
962948Sphk		WRONG
972886Sphk	    }
982886Sphk	    if(cnt != write(i,trash,cnt)) {
992886Sphk		perror(name);
1002948Sphk		WRONG
1012886Sphk	    }
1022886Sphk	    close(i);
1039491Sphk	    if(strcmp(md5,MD5File(name,md5_1))) {
1042886Sphk		fprintf(stderr,"  %s %s MD5 didn't come out right\n",
1052886Sphk		   sp->Key,name);
1062948Sphk		WRONG
1072886Sphk	    }
1082886Sphk	    continue;
1098857Srgrimes	}
1102886Sphk	if(!strcmp(sp->Key,"FE")) {
1112971Sphk	    ed = popen("ed","w");
1122886Sphk	    if(!ed) {
1132886Sphk		WRONG
1142886Sphk	    }
1152971Sphk	    fprintf(ed,"e %s\n",name);
1162886Sphk	    if(cnt != fwrite(trash,1,cnt,ed)) {
1172886Sphk		perror(name);
1182886Sphk		pclose(ed);
1192948Sphk		WRONG
1202886Sphk	    }
1212886Sphk	    fprintf(ed,"w %s\n",name);
1222886Sphk	    if(pclose(ed)) {
1232886Sphk		perror("ed");
1242948Sphk		WRONG
1252886Sphk	    }
1269491Sphk	    if(strcmp(md5,MD5File(name,md5_1))) {
1272886Sphk		fprintf(stderr,"  %s %s MD5 didn't come out right\n",
1282886Sphk		   sp->Key,name);
1292948Sphk		WRONG
1302886Sphk	    }
1312886Sphk	    continue;
1322886Sphk	}
1332926Sphk	if(!strcmp(sp->Key,"FN")) {
1342926Sphk	    strcpy(buf,name);
13513917Sphk	    strcat(buf,TMPSUFF);
1362926Sphk	    i = ctm_edit(trash,cnt,name,buf);
1372926Sphk	    if(i) {
1382948Sphk		fprintf(stderr," %s %s Edit failed with code %d.\n",
1392948Sphk		    sp->Key,name,i);
1402948Sphk	        WRONG
1412926Sphk	    }
1422926Sphk	    rename(buf,name);
1439491Sphk	    if(strcmp(md5,MD5File(name,md5_1))) {
1442948Sphk		fprintf(stderr," %s %s Edit failed MD5 check.\n",
1452948Sphk		    sp->Key,name);
1462948Sphk	        WRONG
1472948Sphk	    }
1482948Sphk	    continue;
1492926Sphk	}
1502886Sphk	if(!strcmp(sp->Key,"DM")) {
1517372Sjoerg	    if(0 > mkdir(name,0777)) {
1522886Sphk		sprintf(buf,"mkdir -p %s",name);
1532886Sphk		system(buf);
1542886Sphk	    }
1552886Sphk	    if(0 > stat(name,&st) || ((st.st_mode & S_IFMT) != S_IFDIR)) {
1562886Sphk		fprintf(stderr,"<%s> mkdir failed\n",name);
1572948Sphk		WRONG
1582886Sphk	    }
1592886Sphk	    continue;
1608857Srgrimes	}
1614816Sphk	if(!strcmp(sp->Key,"FR")) {
1624947Sphk	    if (0 != unlink(name)) {
1634947Sphk		fprintf(stderr,"<%s> unlink failed\n",name);
1646181Sphk		if (!Force)
1656181Sphk		    WRONG
1664947Sphk	    }
1674947Sphk	    continue;
1688857Srgrimes	}
1698857Srgrimes	if(!strcmp(sp->Key,"DR")) {
1704947Sphk	    /*
1714947Sphk	     * We cannot use rmdir() because we do not get the directories
1724947Sphk	     * in '-depth' order (cvs-cur.0018.gz for examples)
1734947Sphk	     */
1744816Sphk	    sprintf(buf,"rm -rf %s",name);
1754816Sphk	    system(buf);
1762886Sphk	    continue;
1778857Srgrimes	}
1782886Sphk	WRONG
1792886Sphk    }
18013917Sphk
18113917Sphk    Delete(md5);
18213917Sphk    Delete(uid);
18313917Sphk    Delete(gid);
18413917Sphk    Delete(mode);
18513917Sphk    Delete(md5before);
18613917Sphk    Delete(trash);
18713917Sphk    Delete(name);
18813917Sphk
1899491Sphk    q = MD5End (&ctx,md5_1);
1902886Sphk    GETFIELD(p,'\n');
1912886Sphk    if(strcmp(q,p)) WRONG
1922886Sphk    if (-1 != getc(fd)) WRONG
1932886Sphk    return 0;
1942886Sphk}
195