ctm_pass3.c revision 4839
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: ctm_pass3.c,v 1.5 1994/11/26 08:57:42 phk Exp $ 10 * 11 */ 12 13#include "ctm.h" 14#define BADREAD 32 15 16/*---------------------------------------------------------------------------*/ 17/* Pass3 -- Validate the incoming 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","w"); 111 if(!ed) { 112 WRONG 113 } 114 fprintf(ed,"e %s\n",name); 115 if(cnt != fwrite(trash,1,cnt,ed)) { 116 perror(name); 117 pclose(ed); 118 WRONG 119 } 120 fprintf(ed,"w %s\n",name); 121 if(pclose(ed)) { 122 perror("ed"); 123 WRONG 124 } 125 if(strcmp(md5,MD5File(name))) { 126 fprintf(stderr," %s %s MD5 didn't come out right\n", 127 sp->Key,name); 128 WRONG 129 } 130 continue; 131 } 132 if(!strcmp(sp->Key,"FN")) { 133 strcpy(buf,name); 134 strcat(buf,".ctm"); 135 i = ctm_edit(trash,cnt,name,buf); 136 if(i) { 137 fprintf(stderr," %s %s Edit failed with code %d.\n", 138 sp->Key,name,i); 139 WRONG 140 } 141 rename(buf,name); 142 if(strcmp(md5,MD5File(name))) { 143 fprintf(stderr," %s %s Edit failed MD5 check.\n", 144 sp->Key,name); 145 WRONG 146 } 147 continue; 148 } 149 if(!strcmp(sp->Key,"DM")) { 150 if(0 > mkdir(name,0755)) { 151 sprintf(buf,"mkdir -p %s",name); 152 system(buf); 153 } 154 if(0 > stat(name,&st) || ((st.st_mode & S_IFMT) != S_IFDIR)) { 155 fprintf(stderr,"<%s> mkdir failed\n",name); 156 WRONG 157 } 158 continue; 159 } 160 if(!strcmp(sp->Key,"FR")) { 161 if (0 == unlink(name)) 162 continue; 163 } 164 if(!strcmp(sp->Key,"DR")) { 165 if (0 == rmdir(name)) 166 continue; 167#ifdef NOTDEF 168 sprintf(buf,"rm -rf %s",name); 169 system(buf); 170 continue; 171#endif 172 } 173 WRONG 174 } 175 q = MD5End (&ctx); 176 GETFIELD(p,'\n'); 177 if(strcmp(q,p)) WRONG 178 if (-1 != getc(fd)) WRONG 179 return 0; 180} 181