2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> 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 * ----------------------------------------------------------------------------
16 /*---------------------------------------------------------------------------*/
17 /* Pass2 -- Validate the incoming CTM-file.
25 int i,j,sep,cnt,fdesc;
26 u_char *trash=0,*name=0;
27 struct CTM_Syntax *sp;
32 struct CTM_Filter *filter;
34 static char *template = NULL;
37 printf("Pass2 -- Checking if CTM-patch will apply\n");
40 GETFIELD(p,' '); if(strcmp("CTM_BEGIN",p)) WRONG
41 GETFIELD(p,' '); if(strcmp(Version,p)) WRONG
42 GETFIELD(p,' '); if(strcmp(Name,p)) WRONG
43 /* XXX Lookup name in /etc/ctm,conf, read stuff */
44 GETFIELD(p,' '); if(strcmp(Nbr,p)) WRONG
45 /* XXX Verify that this is the next patch to apply */
46 GETFIELD(p,' '); if(strcmp(TimeStamp,p)) WRONG
47 GETFIELD(p,'\n'); if(strcmp(Prefix,p)) WRONG
48 /* XXX drop or use ? */
56 /* if a filter list was specified, check file name against
58 if no filter was given operate on all files. */
60 !(FilterList->Action) : CTM_FILTER_ENABLE);
64 if (p[0] != 'C' || p[1] != 'T' || p[2] != 'M') WRONG
66 if(!strcmp(p+3,"_END"))
69 for(sp=Syntax;sp->Key;sp++)
70 if(!strcmp(p+3,sp->Key))
74 for(i=0;(j = sp->List[i]);i++) {
75 if (sp->List[i+1] && (sp->List[i+1] & CTM_F_MASK) != CTM_F_Bytes)
80 switch (j & CTM_F_MASK) {
82 GETNAMECOPY(name,sep,j,0);
83 /* If `keep' was specified, we won't remove any files,
84 so don't check if the file exists */
86 (!strcmp(sp->Key,"FR") || !strcmp(sp->Key,"DR"))) {
87 match = CTM_FILTER_DISABLE;
91 for (filter = FilterList; filter; filter = filter->Next) if (0 == regexec(&filter->CompiledRegex, name,
93 match = filter->Action;
96 if (CTM_FILTER_DISABLE == match)
97 break; /* should ignore this file */
99 /* XXX Check DR DM rec's for parent-dir */
100 if(j & CTM_Q_Name_New) {
101 /* XXX Check DR FR rec's for item */
102 if(-1 != stat(name,&st)) {
103 fprintf(stderr," %s: %s exists.\n",
105 ret |= Exit_Forcible;
109 if(-1 == stat(name,&st)) {
110 fprintf(stderr," %s: %s doesn't exist.\n",
112 if (sp->Key[1] == 'R')
113 ret |= Exit_Forcible;
118 if (SetTime && getuid() && (getuid() != st.st_uid)) {
120 " %s: %s not mine, cannot set time.\n",
124 if (j & CTM_Q_Name_Dir) {
125 if((st.st_mode & S_IFMT) != S_IFDIR) {
127 " %s: %s exist, but isn't dir.\n",
133 if (j & CTM_Q_Name_File) {
134 if((st.st_mode & S_IFMT) != S_IFREG) {
136 " %s: %s exist, but isn't file.\n",
150 if(j & CTM_Q_MD5_Before) {
153 if(match && (st.st_mode & S_IFMT) == S_IFREG &&
154 (tmp = MD5File(name,md5_1)) != NULL &&
156 fprintf(stderr," %s: %s md5 mismatch.\n",
158 GETFIELDCOPY(md5,sep);
159 if(md5 != NULL && strcmp(tmp,md5) == 0) {
160 fprintf(stderr," %s: %s already applied.\n",
162 match = CTM_FILTER_DISABLE;
163 } else if(j & CTM_Q_MD5_Force) {
165 fprintf(stderr," Can and will force.\n");
167 fprintf(stderr," Could have forced.\n");
168 ret |= Exit_Forcible;
174 } else if(j & CTM_Q_MD5_After) {
176 GETFIELDCOPY(md5,sep);
180 /* Unqualified MD5 */
192 if (asprintf(&template, "%s/CTMclientXXXXXX",
194 fprintf(stderr, " %s: malloc failed.\n",
200 if(!strcmp(sp->Key,"FN")) {
201 if ((p = strdup(template)) == NULL) {
202 fprintf(stderr, " %s: malloc failed.\n",
207 if ((fdesc = mkstemp(p)) == -1) {
208 fprintf(stderr, " %s: mkstemp failed.\n",
214 if (close(fdesc) == -1) {
215 fprintf(stderr, " %s: close failed.\n",
222 j = ctm_edit(trash,cnt,name,p);
224 fprintf(stderr," %s: %s edit returned %d.\n",
230 } else if(strcmp(md5,MD5File(p,md5_1))) {
231 fprintf(stderr," %s: %s edit fails.\n",
240 } else if (!strcmp(sp->Key,"FE")) {
241 if ((p = strdup(template)) == NULL) {
242 fprintf(stderr, " %s: malloc failed.\n",
247 if ((fdesc = mkstemp(p)) == -1) {
248 fprintf(stderr, " %s: mkstemp failed.\n",
254 if (close(fdesc) == -1) {
255 fprintf(stderr, " %s: close failed.\n",
262 ed = popen("ed","w");
266 fprintf(ed,"e %s\n", name);
267 if (cnt != fwrite(trash,1,cnt,ed)) {
272 fprintf(ed,"w %s\n",p);
277 if(strcmp(md5,MD5File(p,md5_1))) {
278 fprintf(stderr,"%s %s MD5 didn't come out right\n",
296 q = MD5End (&ctx,md5_1);
297 GETFIELD(p,'\n'); /* <MD5> */
298 if(strcmp(q,p)) WRONG
299 if (-1 != getc(fd)) WRONG