ctm_pass3.c revision 2948
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 /* XXX This should go away. Disallow trailing '/' */ 87 j = strlen(name)-1; 88 if(name[j] == '/') name[j] = '\0'; 89 90 fprintf(stderr,"> %s %s\n",sp->Key,name); 91 if(!strcmp(sp->Key,"FM") || !strcmp(sp->Key, "FS")) { 92 i = open(name,O_WRONLY|O_CREAT|O_TRUNC,0644); 93 if(i < 0) { 94 perror(name); 95 WRONG 96 } 97 if(cnt != write(i,trash,cnt)) { 98 perror(name); 99 WRONG 100 } 101 close(i); 102 if(strcmp(md5,MD5File(name))) { 103 fprintf(stderr," %s %s MD5 didn't come out right\n", 104 sp->Key,name); 105 WRONG 106 } 107 continue; 108 } 109 if(!strcmp(sp->Key,"FE")) { 110 ed = popen("ed -s","w"); 111 if(!ed) { 112 WRONG 113 } 114 if(cnt != fwrite(trash,1,cnt,ed)) { 115 perror(name); 116 pclose(ed); 117 WRONG 118 } 119 fprintf(ed,"w %s\n",name); 120 if(pclose(ed)) { 121 perror("ed"); 122 WRONG 123 } 124 if(strcmp(md5,MD5File(name))) { 125 fprintf(stderr," %s %s MD5 didn't come out right\n", 126 sp->Key,name); 127 WRONG 128 } 129 continue; 130 } 131 if(!strcmp(sp->Key,"FN")) { 132 strcpy(buf,name); 133 strcat(buf,".ctm"); 134 i = ctm_edit(trash,cnt,name,buf); 135 if(i) { 136 fprintf(stderr," %s %s Edit failed with code %d.\n", 137 sp->Key,name,i); 138 WRONG 139 } 140 rename(buf,name); 141 if(strcmp(md5,MD5File(name))) { 142 fprintf(stderr," %s %s Edit failed MD5 check.\n", 143 sp->Key,name); 144 WRONG 145 } 146 continue; 147 } 148 if(!strcmp(sp->Key,"DM")) { 149 if(0 > mkdir(name,0755)) { 150 sprintf(buf,"mkdir -p %s",name); 151 system(buf); 152 } 153 if(0 > stat(name,&st) || ((st.st_mode & S_IFMT) != S_IFDIR)) { 154 fprintf(stderr,"<%s> mkdir failed\n",name); 155 WRONG 156 } 157 continue; 158 } 159 if(!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR")) { 160 if(0 > unlink(name)) { 161 sprintf(buf,"rm -rf %s",name); 162 system(buf); 163 } 164 continue; 165 } 166 WRONG 167 } 168 q = MD5End (&ctx); 169 GETFIELD(p,'\n'); 170 if(strcmp(q,p)) WRONG 171 if (-1 != getc(fd)) WRONG 172 return 0; 173} 174