$OpenBSD: patch-ctm_ctm_ctm_passb_c,v 1.2 2007/10/31 23:14:46 ajacoutot Exp $ --- ctm/ctm/ctm_passb.c.orig Wed Oct 31 23:09:23 2007 +++ ctm/ctm/ctm_passb.c Wed Oct 31 23:10:13 2007 @@ -0,0 +1,141 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Joseph Koshy + * ---------------------------------------------------------------------------- + * + * + */ + +#include "ctm.h" +#define BADREAD 32 + +/*---------------------------------------------------------------------------*/ +/* PassB -- Backup modified files. + */ + +int +PassB(FILE *fd) +{ + u_char *p,*q; + MD5_CTX ctx; + int i,j,sep,cnt; + u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0; + struct CTM_Syntax *sp; + FILE *b = 0; /* backup command */ + u_char buf[BUFSIZ]; + char md5_1[33]; + int ret = 0; + int match = 0; + struct CTM_Filter *filter = NULL; + + if(Verbose>3) + printf("PassB -- Backing up files which would be changed.\n"); + + MD5Init (&ctx); + sprintf(buf, TarCmd, BackupFile); + b=popen(buf, "w"); + if(!b) { warn("%s", buf); return Exit_Garbage; } + + GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG + GETFIELD(p,' '); if(strcmp(Version,p)) WRONG + GETFIELD(p,' '); if(strcmp(Name,p)) WRONG + GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG + GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG + GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG + + for(;;) { + Delete(md5); + Delete(uid); + Delete(gid); + Delete(mode); + Delete(md5before); + Delete(trash); + Delete(name); + cnt = -1; + + GETFIELD(p,' '); + + if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG + + if(!strcmp(p+3,"_END")) + break; + + for(sp=Syntax;sp->Key;sp++) + if(!strcmp(p+3,sp->Key)) + goto found; + WRONG + found: + for(i=0;(j = sp->List[i]);i++) { + if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes) + sep = ' '; + else + sep = '\n'; + + switch (j & CTM_F_MASK) { + case CTM_F_Name: GETNAMECOPY(name,sep,j, Verbose); break; + case CTM_F_Uid: GETFIELDCOPY(uid,sep); break; + case CTM_F_Gid: GETFIELDCOPY(gid,sep); break; + case CTM_F_Mode: GETFIELDCOPY(mode,sep); break; + case CTM_F_MD5: + if(j & CTM_Q_MD5_Before) + GETFIELDCOPY(md5before,sep); + else + GETFIELDCOPY(md5,sep); + break; + case CTM_F_Count: GETBYTECNT(cnt,sep); break; + case CTM_F_Bytes: GETDATA(trash,cnt); break; + default: WRONG + } + } + /* XXX This should go away. Disallow trailing '/' */ + j = strlen(name)-1; + if(name[j] == '/') name[j] = '\0'; + + if (KeepIt && + (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR"))) + continue; + + /* match the name against the elements of the filter list. The + action associated with the last matched filter determines whether + this file should be ignored or backed up. */ + match = (FilterList ? !(FilterList->Action) : CTM_FILTER_ENABLE); + for (filter = FilterList; filter; filter = filter->Next) { + if (0 == regexec(&filter->CompiledRegex, name, 0, 0, 0)) + match = filter->Action; + } + + if (CTM_FILTER_DISABLE == match) + continue; + + if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") || + !strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") || + !strcmp(sp->Key,"FR")) { + /* send name to the archiver for a backup */ + cnt = strlen(name); + if (cnt != fwrite(name,1,cnt,b) || EOF == fputc('\n',b)) { + warn("%s", name); + pclose(b); + WRONG; + } + } + } + + ret = pclose(b); + + Delete(md5); + Delete(uid); + Delete(gid); + Delete(mode); + Delete(md5before); + Delete(trash); + Delete(name); + + q = MD5End (&ctx,md5_1); + GETFIELD(p,'\n'); /* */ + if(strcmp(q,p)) WRONG + if (-1 != getc(fd)) WRONG + return ret; +}