117946Sphk/*
217946Sphk * ----------------------------------------------------------------------------
317946Sphk * "THE BEER-WARE LICENSE" (Revision 42):
417946Sphk * <koshy@india.hp.com> wrote this file.  As long as you retain this notice you
517946Sphk * can do whatever you want with this stuff. If we meet some day, and you think
617946Sphk * this stuff is worth it, you can buy me a beer in return.   Joseph Koshy
717946Sphk * ----------------------------------------------------------------------------
817946Sphk *
950479Speter * $FreeBSD$
1017946Sphk *
1117946Sphk */
1217946Sphk
1317946Sphk#include "ctm.h"
1417946Sphk#define BADREAD 32
1517946Sphk
1617946Sphk/*---------------------------------------------------------------------------*/
1717946Sphk/* PassB -- Backup modified files.
1817946Sphk */
1917946Sphk
2017946Sphkint
2117946SphkPassB(FILE *fd)
2217946Sphk{
2317946Sphk    u_char *p,*q;
2417946Sphk    MD5_CTX ctx;
2517946Sphk    int i,j,sep,cnt;
2617946Sphk    u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0;
2717946Sphk    struct CTM_Syntax *sp;
2817946Sphk    FILE *b = 0;	/* backup command */
2917946Sphk    u_char buf[BUFSIZ];
3017946Sphk    char md5_1[33];
3117946Sphk    int ret = 0;
3217946Sphk    int match = 0;
3317946Sphk    struct CTM_Filter *filter = NULL;
3417946Sphk
3517946Sphk    if(Verbose>3)
3617946Sphk	printf("PassB -- Backing up files which would be changed.\n");
3717946Sphk
3817946Sphk    MD5Init (&ctx);
3976300Skris    snprintf(buf, sizeof(buf), fmtcheck(TarCmd, TARCMD), BackupFile);
4017946Sphk    b=popen(buf, "w");
4129526Scharnier    if(!b) { warn("%s", buf); return Exit_Garbage; }
4217946Sphk
4317946Sphk    GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
4417946Sphk    GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
4517946Sphk    GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
4617946Sphk    GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
4717946Sphk    GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
4817946Sphk    GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
4917946Sphk
5017946Sphk    for(;;) {
5117946Sphk	Delete(md5);
5217946Sphk	Delete(uid);
5317946Sphk	Delete(gid);
5417946Sphk	Delete(mode);
5517946Sphk	Delete(md5before);
5617946Sphk	Delete(trash);
5717946Sphk	Delete(name);
5817946Sphk	cnt = -1;
5917946Sphk
6017946Sphk	GETFIELD(p,' ');
6117946Sphk
6217946Sphk	if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
6317946Sphk
6417946Sphk	if(!strcmp(p+3,"_END"))
6517946Sphk	    break;
6617946Sphk
6717946Sphk	for(sp=Syntax;sp->Key;sp++)
6817946Sphk	    if(!strcmp(p+3,sp->Key))
6917946Sphk		goto found;
7017946Sphk	WRONG
7117946Sphk    found:
7217946Sphk	for(i=0;(j = sp->List[i]);i++) {
7317946Sphk	    if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
7417946Sphk		sep = ' ';
7517946Sphk	    else
7617946Sphk		sep = '\n';
7717946Sphk
7817946Sphk	    switch (j & CTM_F_MASK) {
7917946Sphk		case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break;
8017946Sphk		case CTM_F_Uid:  GETFIELDCOPY(uid,sep); break;
8117946Sphk		case CTM_F_Gid:  GETFIELDCOPY(gid,sep); break;
8217946Sphk		case CTM_F_Mode: GETFIELDCOPY(mode,sep); break;
8317946Sphk		case CTM_F_MD5:
8417946Sphk		    if(j & CTM_Q_MD5_Before)
8517946Sphk			GETFIELDCOPY(md5before,sep);
8617946Sphk		    else
8717946Sphk			GETFIELDCOPY(md5,sep);
8817946Sphk		    break;
8917946Sphk		case CTM_F_Count: GETBYTECNT(cnt,sep); break;
9017946Sphk		case CTM_F_Bytes: GETDATA(trash,cnt); break;
9117946Sphk		default: WRONG
9217946Sphk		}
9317946Sphk	    }
9417946Sphk	/* XXX This should go away.  Disallow trailing '/' */
9517946Sphk	j = strlen(name)-1;
9617946Sphk	if(name[j] == '/') name[j] = '\0';
9717946Sphk
9817946Sphk	if (KeepIt &&
9917946Sphk	    (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")))
10017946Sphk	    continue;
10117946Sphk
10217946Sphk	/* match the name against the elements of the filter list.  The
10317946Sphk	   action associated with the last matched filter determines whether
10417946Sphk	   this file should be ignored or backed up. */
10517946Sphk	match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE);
10617946Sphk	for (filter = FilterList; filter; filter = filter->Next) {
10717946Sphk	    if (0 == regexec(&filter->CompiledRegex, name, 0, 0, 0))
10817946Sphk		match = filter->Action;
10917946Sphk	}
11017946Sphk
11117946Sphk	if (CTM_FILTER_DISABLE == match)
11217946Sphk		continue;
11317946Sphk
11417946Sphk	if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") ||
11517946Sphk	    !strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") ||
11617946Sphk	    !strcmp(sp->Key,"FR")) {
11717946Sphk	    /* send name to the archiver for a backup */
11817946Sphk	    cnt = strlen(name);
11917946Sphk	    if (cnt != fwrite(name,1,cnt,b) || EOF == fputc('\n',b)) {
12029526Scharnier		warn("%s", name);
12117946Sphk		pclose(b);
12217946Sphk		WRONG;
12317946Sphk	    }
12417946Sphk	}
12517946Sphk    }
12617946Sphk
12717946Sphk    ret = pclose(b);
12817946Sphk
12917946Sphk    Delete(md5);
13017946Sphk    Delete(uid);
13117946Sphk    Delete(gid);
13217946Sphk    Delete(mode);
13317946Sphk    Delete(md5before);
13417946Sphk    Delete(trash);
13517946Sphk    Delete(name);
13617946Sphk
13717946Sphk    q = MD5End (&ctx,md5_1);
13817946Sphk    GETFIELD(p,'\n');			/* <MD5> */
13917946Sphk    if(strcmp(q,p)) WRONG
14017946Sphk    if (-1 != getc(fd)) WRONG
14117946Sphk    return ret;
14217946Sphk}
143