12926Sphk/* 22926Sphk * ---------------------------------------------------------------------------- 32926Sphk * "THE BEER-WARE LICENSE" (Revision 42): 493150Sphk * <phk@FreeBSD.org> 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 * 950479Speter * $FreeBSD$ 102926Sphk * 112926Sphk */ 122926Sphk 132886Sphk#include "ctm.h" 142926Sphk#define BADREAD 32 152886Sphk 162886Sphk/*---------------------------------------------------------------------------*/ 174816Sphk/* Pass2 -- Validate the incoming CTM-file. 182886Sphk */ 192886Sphk 202886Sphkint 212886SphkPass2(FILE *fd) 222886Sphk{ 232926Sphk u_char *p,*q,*md5=0; 242886Sphk MD5_CTX ctx; 2576300Skris int i,j,sep,cnt,fdesc; 262886Sphk u_char *trash=0,*name=0; 272886Sphk struct CTM_Syntax *sp; 282886Sphk struct stat st; 292926Sphk int ret = 0; 3017946Sphk int match = 0; 319491Sphk char md5_1[33]; 3217946Sphk struct CTM_Filter *filter; 3317946Sphk FILE *ed = NULL; 3476300Skris static char *template = NULL; 352886Sphk 368857Srgrimes if(Verbose>3) 372886Sphk printf("Pass2 -- Checking if CTM-patch will apply\n"); 382886Sphk MD5Init (&ctx); 392886Sphk 402886Sphk GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG 412886Sphk GETFIELD(p,' '); if(strcmp(Version,p)) WRONG 422886Sphk GETFIELD(p,' '); if(strcmp(Name,p)) WRONG 432886Sphk /* XXX Lookup name in /etc/ctm,conf, read stuff */ 442886Sphk GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG 452886Sphk /* XXX Verify that this is the next patch to apply */ 462886Sphk GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG 472886Sphk GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG 482886Sphk /* XXX drop or use ? */ 492886Sphk 502886Sphk for(;;) { 5113917Sphk Delete(trash); 5213917Sphk Delete(name); 5313917Sphk Delete(md5); 542886Sphk cnt = -1; 552886Sphk 5617946Sphk /* if a filter list was specified, check file name against 5717946Sphk the filters specified 5817946Sphk if no filter was given operate on all files. */ 5917946Sphk match = (FilterList ? 6017946Sphk !(FilterList->Action) : CTM_FILTER_ENABLE); 6117946Sphk 622886Sphk GETFIELD(p,' '); 632886Sphk 642886Sphk if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG 652886Sphk 662886Sphk if(!strcmp(p+3,"_END")) 672886Sphk break; 682886Sphk 692886Sphk for(sp=Syntax;sp->Key;sp++) 702886Sphk if(!strcmp(p+3,sp->Key)) 712886Sphk goto found; 722886Sphk WRONG 732886Sphk found: 742886Sphk for(i=0;(j = sp->List[i]);i++) { 752886Sphk if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes) 762886Sphk sep = ' '; 772886Sphk else 782886Sphk sep = '\n'; 792886Sphk 802886Sphk switch (j & CTM_F_MASK) { 812886Sphk case CTM_F_Name: 8213917Sphk GETNAMECOPY(name,sep,j,0); 8317946Sphk /* If `keep' was specified, we won't remove any files, 8417946Sphk so don't check if the file exists */ 8517946Sphk if (KeepIt && 8617946Sphk (!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) { 8717946Sphk match = CTM_FILTER_DISABLE; 8817946Sphk break; 8917946Sphk } 9017946Sphk 9117946Sphk for (filter = FilterList; filter; filter = filter->Next) if (0 == regexec(&filter->CompiledRegex, name, 9217946Sphk 0, 0, 0)) { 9317946Sphk match = filter->Action; 9417946Sphk } 9517946Sphk 9617946Sphk if (CTM_FILTER_DISABLE == match) 9717946Sphk break; /* should ignore this file */ 9817946Sphk 992886Sphk /* XXX Check DR DM rec's for parent-dir */ 1002886Sphk if(j & CTM_Q_Name_New) { 1012886Sphk /* XXX Check DR FR rec's for item */ 1022886Sphk if(-1 != stat(name,&st)) { 1032926Sphk fprintf(stderr," %s: %s exists.\n", 1042926Sphk sp->Key,name); 1052971Sphk ret |= Exit_Forcible; 1062886Sphk } 1072886Sphk break; 1082886Sphk } 1092886Sphk if(-1 == stat(name,&st)) { 1106181Sphk fprintf(stderr," %s: %s doesn't exist.\n", 1112886Sphk sp->Key,name); 1126181Sphk if (sp->Key[1] == 'R') 1136181Sphk ret |= Exit_Forcible; 1146181Sphk else 1156181Sphk ret |= Exit_NotOK; 1162886Sphk break; 1178857Srgrimes } 11815456Sphk if (SetTime && getuid() && (getuid() != st.st_uid)) { 11915456Sphk fprintf(stderr, 12015456Sphk " %s: %s not mine, cannot set time.\n", 12115456Sphk sp->Key,name); 12215456Sphk ret |= Exit_NotOK; 12315456Sphk } 1242886Sphk if (j & CTM_Q_Name_Dir) { 1252926Sphk if((st.st_mode & S_IFMT) != S_IFDIR) { 1262886Sphk fprintf(stderr, 1272886Sphk " %s: %s exist, but isn't dir.\n", 1282886Sphk sp->Key,name); 1292971Sphk ret |= Exit_NotOK; 1302926Sphk } 1312886Sphk break; 1328857Srgrimes } 1332886Sphk if (j & CTM_Q_Name_File) { 1342926Sphk if((st.st_mode & S_IFMT) != S_IFREG) { 1352886Sphk fprintf(stderr, 1362886Sphk " %s: %s exist, but isn't file.\n", 1372886Sphk sp->Key,name); 1382971Sphk ret |= Exit_NotOK; 1392926Sphk } 1402886Sphk break; 1412886Sphk } 1422886Sphk break; 1432886Sphk case CTM_F_Uid: 1442886Sphk case CTM_F_Gid: 1452886Sphk case CTM_F_Mode: 1462886Sphk GETFIELD(p,sep); 1472886Sphk break; 1482886Sphk case CTM_F_MD5: 1492886Sphk if(!name) WRONG 1502926Sphk if(j & CTM_Q_MD5_Before) { 15112190Sphk char *tmp; 1522926Sphk GETFIELD(p,sep); 15317946Sphk if(match && (st.st_mode & S_IFMT) == S_IFREG && 15412190Sphk (tmp = MD5File(name,md5_1)) != NULL && 15512190Sphk strcmp(tmp,p)) { 1562926Sphk fprintf(stderr," %s: %s md5 mismatch.\n", 1572926Sphk sp->Key,name); 15856056Sphk GETFIELDCOPY(md5,sep); 15956056Sphk if(md5 != NULL && strcmp(tmp,md5) == 0) { 16056056Sphk fprintf(stderr," %s: %s already applied.\n", 16156056Sphk sp->Key,name); 16256056Sphk match = CTM_FILTER_DISABLE; 16356056Sphk } else if(j & CTM_Q_MD5_Force) { 1642971Sphk if(Force) 1652971Sphk fprintf(stderr," Can and will force.\n"); 1662971Sphk else 1677159Sroberto fprintf(stderr," Could have forced.\n"); 1682971Sphk ret |= Exit_Forcible; 1692971Sphk } else { 1702971Sphk ret |= Exit_NotOK; 1712971Sphk } 1722886Sphk } 1732926Sphk break; 17456056Sphk } else if(j & CTM_Q_MD5_After) { 17556056Sphk if(md5 == NULL) { 17656056Sphk GETFIELDCOPY(md5,sep); 17756056Sphk } 1782926Sphk break; 1792926Sphk } 1802926Sphk /* Unqualified MD5 */ 1812971Sphk WRONG 1822886Sphk break; 1832886Sphk case CTM_F_Count: 1842886Sphk GETBYTECNT(cnt,sep); 1852886Sphk break; 1862886Sphk case CTM_F_Bytes: 1872886Sphk if(cnt < 0) WRONG 1882886Sphk GETDATA(trash,cnt); 18917946Sphk if (!match) 19017946Sphk break; 19176300Skris if (!template) { 19276300Skris if (asprintf(&template, "%s/CTMclientXXXXXX", 19376300Skris TmpDir) == -1) { 19476300Skris fprintf(stderr, " %s: malloc failed.\n", 19576300Skris sp->Key); 19676300Skris ret |= Exit_Mess; 19776300Skris return ret; 19876300Skris } 19976300Skris } 2002926Sphk if(!strcmp(sp->Key,"FN")) { 20176300Skris if ((p = strdup(template)) == NULL) { 20276300Skris fprintf(stderr, " %s: malloc failed.\n", 20376300Skris sp->Key); 20476300Skris ret |= Exit_Mess; 20576300Skris return ret; 20676300Skris } 20776300Skris if ((fdesc = mkstemp(p)) == -1) { 20876300Skris fprintf(stderr, " %s: mkstemp failed.\n", 20976300Skris sp->Key); 21076300Skris ret |= Exit_Mess; 21176300Skris Free(p); 21276300Skris return ret; 21376300Skris } 21476300Skris if (close(fdesc) == -1) { 21576300Skris fprintf(stderr, " %s: close failed.\n", 21676300Skris sp->Key); 21776300Skris ret |= Exit_Mess; 21876300Skris unlink(p); 21976300Skris Free(p); 22076300Skris return ret; 22176300Skris } 2222948Sphk j = ctm_edit(trash,cnt,name,p); 2232948Sphk if(j) { 2242948Sphk fprintf(stderr," %s: %s edit returned %d.\n", 2252948Sphk sp->Key,name,j); 2262948Sphk ret |= j; 22715456Sphk unlink(p); 22815456Sphk Free(p); 2292948Sphk return ret; 2309491Sphk } else if(strcmp(md5,MD5File(p,md5_1))) { 2312926Sphk fprintf(stderr," %s: %s edit fails.\n", 2322926Sphk sp->Key,name); 2332971Sphk ret |= Exit_Mess; 23415456Sphk unlink(p); 23515456Sphk Free(p); 2362948Sphk return ret; 2372926Sphk } 23815456Sphk unlink(p); 23913917Sphk Free(p); 24017946Sphk } else if (!strcmp(sp->Key,"FE")) { 24176300Skris if ((p = strdup(template)) == NULL) { 24276300Skris fprintf(stderr, " %s: malloc failed.\n", 24376300Skris sp->Key); 24476300Skris ret |= Exit_Mess; 24576300Skris return ret; 24676300Skris } 24776300Skris if ((fdesc = mkstemp(p)) == -1) { 24876300Skris fprintf(stderr, " %s: mkstemp failed.\n", 24976300Skris sp->Key); 25076300Skris ret |= Exit_Mess; 25176300Skris Free(p); 25276300Skris return ret; 25376300Skris } 25476300Skris if (close(fdesc) == -1) { 25576300Skris fprintf(stderr, " %s: close failed.\n", 25676300Skris sp->Key); 25776300Skris ret |= Exit_Mess; 25876300Skris unlink(p); 25976300Skris Free(p); 26076300Skris return ret; 26176300Skris } 26217946Sphk ed = popen("ed","w"); 26317946Sphk if (!ed) { 26417946Sphk WRONG 26517946Sphk } 26617946Sphk fprintf(ed,"e %s\n", name); 26717946Sphk if (cnt != fwrite(trash,1,cnt,ed)) { 26829526Scharnier warn("%s", name); 26917946Sphk pclose(ed); 27017946Sphk WRONG 27117946Sphk } 27217946Sphk fprintf(ed,"w %s\n",p); 27317946Sphk if (pclose(ed)) { 27429526Scharnier warn("%s", p); 27517946Sphk WRONG 27617946Sphk } 27717946Sphk if(strcmp(md5,MD5File(p,md5_1))) { 27817946Sphk fprintf(stderr,"%s %s MD5 didn't come out right\n", 27917946Sphk sp->Key, name); 28017946Sphk WRONG 28117946Sphk } 28217946Sphk unlink(p); 28317946Sphk Free(p); 2842926Sphk } 2858857Srgrimes 2862886Sphk break; 2872886Sphk default: WRONG 2882886Sphk } 2892886Sphk } 2902886Sphk } 29113917Sphk 29213917Sphk Delete(trash); 29313917Sphk Delete(name); 29413917Sphk Delete(md5); 29513917Sphk 2969491Sphk q = MD5End (&ctx,md5_1); 2972886Sphk GETFIELD(p,'\n'); /* <MD5> */ 2982886Sphk if(strcmp(q,p)) WRONG 2992886Sphk if (-1 != getc(fd)) WRONG 3002926Sphk return ret; 3012886Sphk} 302